Skip to content

Commit

Permalink
fix emulate clause.value cannot be number error, add example of fee d…
Browse files Browse the repository at this point in the history
…elegation
  • Loading branch information
laalaguer committed Jan 12, 2022
1 parent ff0354a commit dce693c
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 6 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
wheel
twine
requests
thor-devkit>=1.0.11
thor-devkit>=1.0.12
pytest
pytest-cov
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setuptools.setup(
name="thor-requests",
version="1.2.0",
version="1.2.1",
author="laalaguer",
author_email="[email protected]",
description="Simple network VeChain SDK for human to interact with the blockchain",
Expand Down
73 changes: 70 additions & 3 deletions tests/test_fee_delegation.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def test_sign_fee_delegation_allow(
delegated_tx = transaction.Transaction(delegated_body)
raw_tx = '0x' + delegated_tx.encode().hex()

def allPass(tx_payer:str, tx_origin:str, transaction):
def allPass(tx_payer:str, tx_origin:str, txObj:transaction.Transaction):
''' Blindly allow the tx to pass '''
return True, ''

result = utils.sign_delegated_tx(solo_wallet, clean_wallet.getAddress(), raw_tx, False, allPass)
Expand Down Expand Up @@ -163,9 +164,75 @@ def test_sign_fee_delegation_reject(
delegated_tx = transaction.Transaction(delegated_body)
raw_tx = '0x' + delegated_tx.encode().hex()

def allPass(tx_payer:str, tx_origin:str, transaction):
def allPass(tx_payer:str, tx_origin:str, txObj:transaction.Transaction):
return False, 'I just dont allow this tx to pass'

result = utils.sign_delegated_tx(solo_wallet, clean_wallet.getAddress(), raw_tx, False, allPass)
assert len(result['signature']) == 0
assert result['error_message'] == 'I just dont allow this tx to pass'
assert result['error_message'] == 'I just dont allow this tx to pass'


def test_sign_if_emulate_success(
solo_connector,
solo_wallet,
clean_wallet,
vtho_contract_address,
vtho_contract
):
# First, solo wallet send 3 vtho to the clean wallet
res = solo_connector.transfer_vtho(solo_wallet, clean_wallet.getAddress(), 3 * 10 ** 18)
tx_id = res["id"]
receipt = solo_connector.wait_for_tx_receipt(tx_id)
assert utils.is_reverted(receipt) == False

# Then, construct a tx which sends back 3 vtho to solo wallet,
# But tx is sponsored by the solo wallet
chainTag = solo_connector.get_chainTag()
best_block = solo_connector.get_block("best")
blockRef = utils.calc_blockRef(best_block["id"])
nonce = utils.calc_nonce()

clause = solo_connector.clause(vtho_contract, 'transfer', [solo_wallet.getAddress(), 3 * 10 ** 18], vtho_contract_address)
delegated_body = utils.build_tx_body(
[clause.to_dict()],
chainTag,
blockRef,
nonce,
gas=100000,
feeDelegation=True
)

delegated_tx = transaction.Transaction(delegated_body)
raw_tx = '0x' + delegated_tx.encode().hex()

def emulate_then_judge(tx_payer:str, tx_origin:str, txObj:transaction.Transaction):
''' If emulation failed then refuse to sign the transaction '''
old_body = txObj.get_body()
e_responses = solo_connector.emulate_tx(tx_origin, old_body, gas_payer=tx_payer)
if utils.any_emulate_failed(e_responses):
return False, 'Emulation failed'
return True, ''

# Ask for gas payer's signature
result = utils.sign_delegated_tx(solo_wallet, clean_wallet.getAddress(), raw_tx, False, emulate_then_judge)
assert len(result['signature']) > 0
assert len(result['error_message']) == 0

# Assemble tx
user_signagure = clean_wallet.sign(delegated_tx.get_signing_hash())
server_signature = bytes.fromhex(result['signature'].lstrip('0x'))

sig = user_signagure + server_signature

delegated_tx.set_signature(sig)
assert delegated_tx.is_delegated() == True

assert delegated_tx.get_origin() == clean_wallet.getAddress()
assert delegated_tx.get_delegator() == solo_wallet.getAddress()

# Post tx (and should success)
raw_tx_again = "0x" + delegated_tx.encode().hex()
res = solo_connector.post_tx(raw_tx_again)
tx_id = res['id']
receipt = solo_connector.wait_for_tx_receipt(tx_id)
assert utils.is_reverted(receipt) == False
10 changes: 9 additions & 1 deletion thor_requests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,19 @@ def calc_emulate_tx_body(caller: str, tx_body: dict, gaspayer: str=None) -> dict
if not address.is_address(caller):
raise Exception(f"{caller} is not an address")

# Caution: in emulation, clauses.clause.value must be of type string
e_clauses = []
for clause in tx_body['clauses']:
e_clauses.append({
'to': clause['to'],
'value': str(clause['value']),
'data': clause['data']
})
e_tx_body = {
"caller": caller,
"blockRef": tx_body["blockRef"],
"expiration": tx_body["expiration"],
"clauses": tx_body["clauses"],
"clauses": e_clauses,
}

# Set gas field only when the tx_body set it.
Expand Down

0 comments on commit dce693c

Please sign in to comment.