Merge upstream contract migration

This commit is contained in:
nolash
2021-03-23 17:15:27 +01:00
parent d892caa288
commit 353abaa151
10 changed files with 290 additions and 170 deletions

View File

@@ -3,9 +3,11 @@ import logging
# external imports
import celery
from erc20_single_shot_faucet import Faucet
from erc20_single_shot_faucet import SingleShotFaucet as Faucet
from chainlib.eth.constant import ZERO_ADDRESS
from hexathon import strip_0x
from hexathon import (
strip_0x,
)
from chainlib.connection import RPCConnection
from chainlib.eth.sign import (
new_account,
@@ -18,6 +20,7 @@ from chainlib.eth.tx import (
)
from chainlib.chain import ChainSpec
from eth_accounts_index import AccountRegistry
from sarafu_faucet import MinterFaucet as Faucet
# local import
#from cic_eth.registry import safe_registry
@@ -121,23 +124,18 @@ def register(self, account_address, chain_spec_dict, writer_address=None):
# Generate and sign transaction
rpc_signer = RPCConnection.connect(chain_spec, 'signer')
#nonce_oracle = self.create_nonce_oracle(writer_address, rpc)
nonce_oracle = CustodialTaskNonceOracle(writer_address, self.request.root_id, session=session) #, default_nonce)
gas_oracle = self.create_gas_oracle(rpc, AccountRegistry.gas)
account_registry = AccountRegistry(signer=rpc_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_id=chain_spec.chain_id())
(tx_hash_hex, tx_signed_raw_hex) = account_registry.add(account_registry_address, writer_address, account_address, tx_format=TxFormat.RLP_SIGNED)
rpc_signer.disconnect()
# TODO: if cache task fails, task chain will not return
cache_task = 'cic_eth.eth.account.cache_account_data'
# add transaction to queue
cache_task = 'cic_eth.eth.account.cache_account_data'
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task=cache_task, session=session)
session.commit()
session.close()
#gas_budget = tx_add['gas'] * tx_add['gasPrice']
gas_pair = gas_oracle.get_gas(tx_signed_raw_hex)
gas_budget = gas_pair[0] * gas_pair[1]
logg.debug('register user tx {} {} {}'.format(tx_hash_hex, queue, gas_budget))
@@ -156,7 +154,7 @@ def register(self, account_address, chain_spec_dict, writer_address=None):
@celery_app.task(bind=True, base=CriticalSQLAlchemyAndSignerTask)
def gift(self, account_address, chain_str):
def gift(self, account_address, chain_spec_dict):
"""Creates a transaction to invoke the faucet contract for the given address.
:param account_address: Ethereum address to give to
@@ -166,28 +164,39 @@ def gift(self, account_address, chain_str):
:returns: Raw signed transaction
:rtype: list with transaction as only element
"""
chain_spec = ChainSpec.from_chain_str(chain_str)
chain_spec = ChainSpec.from_dict(chain_spec_dict)
logg.debug('gift account address {} to index'.format(account_address))
queue = self.request.delivery_info['routing_key']
queue = self.request.delivery_info.get('routing_key')
c = RpcClient(chain_spec, holder_address=account_address)
registry = safe_registry(c.w3)
txf = AccountTxFactory(account_address, c, registry=registry)
#session = SessionBase.create_session()
# Retrieve account index address
session = self.create_session()
tx_add = txf.gift(account_address, chain_spec, self.request.root_id, session=session)
(tx_hash_hex, tx_signed_raw_hex) = sign_and_register_tx(tx_add, chain_str, queue, 'cic_eth.eth.account.cache_gift_data', session=session)
rpc = RPCConnection.connect(chain_spec, 'default')
registry = CICRegistry(chain_spec, rpc)
faucet_address = registry.by_name('Faucet', sender_address=self.call_address)
# Generate and sign transaction
rpc_signer = RPCConnection.connect(chain_spec, 'signer')
nonce_oracle = CustodialTaskNonceOracle(account_address, self.request.root_id, session=session) #, default_nonce)
gas_oracle = self.create_gas_oracle(rpc, Faucet.gas)
faucet = Faucet(signer=rpc_signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_id=chain_spec.chain_id())
(tx_hash_hex, tx_signed_raw_hex) = faucet.give_to(faucet_address, account_address, account_address, tx_format=TxFormat.RLP_SIGNED)
rpc_signer.disconnect()
# add transaction to queue
cache_task = 'cic_eth.eth.account.cache_gift_data'
register_tx(tx_hash_hex, tx_signed_raw_hex, chain_spec, queue, cache_task, session=session)
session.commit()
session.close()
gas_budget = tx_add['gas'] * tx_add['gasPrice']
gas_pair = gas_oracle.get_gas(tx_signed_raw_hex)
gas_budget = gas_pair[0] * gas_pair[1]
logg.debug('register user tx {} {} {}'.format(tx_hash_hex, queue, gas_budget))
rpc.disconnect()
logg.debug('gift user tx {}'.format(tx_hash_hex))
s = create_check_gas_and_send_task(
s = create_check_gas_task(
[tx_signed_raw_hex],
chain_str,
chain_spec,
account_address,
gas_budget,
[tx_hash_hex],
@@ -199,7 +208,7 @@ def gift(self, account_address, chain_str):
@celery_app.task(bind=True)
def have(self, account, chain_str):
def have(self, account, chain_spec_dict):
"""Check whether the given account exists in keystore
:param account: Account to check
@@ -209,7 +218,7 @@ def have(self, account, chain_str):
:returns: Account, or None if not exists
:rtype: Varies
"""
chain_spec = ChainSpec.from_chain_str(chain_str)
chain_spec = ChainSpec.from_dict(chain_spec_dict)
o = sign_message(account, '0x2a')
try:
conn = RPCConnection.connect(chain_spec, 'signer')
@@ -249,7 +258,7 @@ def cache_gift_data(
self,
tx_hash_hex,
tx_signed_raw_hex,
chain_spec,
chain_spec_dict,
):
"""Generates and commits transaction cache metadata for a Faucet.giveTo transaction
@@ -262,14 +271,12 @@ def cache_gift_data(
:returns: Transaction hash and id of cache element in storage backend, respectively
:rtype: tuple
"""
chain_spec = ChainSpec.from_chain_str(chain_str)
c = RpcClient(chain_spec)
chain_spec = ChainSpec.from_dict(chain_spec_dict)
tx_signed_raw_bytes = bytes.fromhex(tx_signed_raw_hex[2:])
tx_signed_raw_bytes = bytes.fromhex(strip_0x(tx_signed_raw_hex))
tx = unpack(tx_signed_raw_bytes, chain_spec.chain_id())
tx_data = unpack_gift(tx['data'])
tx_data = Faucet.parse_give_to_request(tx['data'])
#session = SessionBase.create_session()
session = self.create_session()
tx_cache = TxCache(
@@ -311,8 +318,7 @@ def cache_account_data(
chain_spec = ChainSpec.from_dict(chain_spec_dict)
tx_signed_raw_bytes = bytes.fromhex(tx_signed_raw_hex[2:])
tx = unpack(tx_signed_raw_bytes, chain_id=chain_spec.chain_id())
raise NotImplementedError('unpack register must be replaced with AccountRegistry parser')
tx_data = unpack_register(tx['data'])
tx_data = AccountRegistry.parse_add_request(tx['data'])
session = SessionBase.create_session()
tx_cache = TxCache(

View File

@@ -7,41 +7,29 @@ from hexathon import (
strip_0x,
add_0x,
)
from chainlib.eth.address import to_checksum
from chainlib.eth.address import to_checksum_address
from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.eth.contract import (
ABIContractType,
abi_decode_single,
)
from cic_eth_registry import CICRegistry
from erc20_transfer_authorization import TransferAuthorization
# local imports
from .base import SyncFilter
logg = logging.getLogger(__name__)
transfer_request_signature = 'ed71262a'
def unpack_create_request(data):
data = strip_0x(data)
cursor = 0
f = data[cursor:cursor+8]
cursor += 8
if f != transfer_request_signature:
raise ValueError('Invalid create request data ({})'.format(f))
o = {}
o['sender'] = data[cursor+24:cursor+64]
cursor += 64
o['recipient'] = data[cursor+24:cursor+64]
cursor += 64
o['token'] = data[cursor+24:cursor+64]
cursor += 64
o['value'] = int(data[cursor:], 16)
return o
class TransferAuthFilter(SyncFilter):
def __init__(self, registry, chain_spec, queue=None):
def __init__(self, registry, chain_spec, conn, queue=None, call_address=ZERO_ADDRESS):
self.queue = queue
self.chain_spec = chain_spec
self.transfer_request_contract = registry.get_contract(self.chain_spec, 'TransferAuthorization')
registry = CICRegistry(chain_spec, conn)
self.transfer_request_contract = registry.by_name('TransferAuthorization', sender_address=call_address)
def filter(self, conn, block, tx, session): #rcpt, chain_str, session=None):
@@ -61,11 +49,13 @@ class TransferAuthFilter(SyncFilter):
logg.debug('not our transfer auth contract address {}'.format(recipient))
return False
o = unpack_create_request(tx.payload)
r = TransferAuthorization.parse_create_request_request(tx.payload)
sender = add_0x(to_checksum(o['sender']))
recipient = add_0x(to_checksum(recipient))
token = add_0x(to_checksum(o['token']))
sender = abi_decode_single(ABIContractType.ADDRESS, r[0])
recipient = abi_decode_single(ABIContractType.ADDRESS, r[1])
token = abi_decode_single(ABIContractType.ADDRESS, r[2])
value = abi_decode_single(ABIContractType.UINT256, r[3])
token_data = {
'address': token,
}
@@ -83,8 +73,8 @@ class TransferAuthFilter(SyncFilter):
[
sender,
recipient,
o['value'],
str(self.chain_spec),
value,
self.chain_spec.asdict(),
],
queue=self.queue,
)

View File

@@ -7,6 +7,8 @@ import time
import pytest
import celery
from chainlib.connection import RPCConnection
from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import receipt
from eth_accounts_index import AccountRegistry
from hexathon import strip_0x
@@ -22,7 +24,6 @@ from cic_eth.db.models.role import AccountRole
logg = logging.getLogger()
@pytest.mark.skip()
def test_create_account(
default_chain_spec,
eth_rpc,
@@ -121,7 +122,6 @@ def test_register_account(
assert int(strip_0x(r), 16) == 1
@pytest.mark.skip()
def test_role_task(
default_chain_spec,
init_database,
@@ -136,9 +136,53 @@ def test_role_task(
'cic_eth.eth.account.role',
[
address,
str(default_chain_spec),
default_chain_spec.asdict(),
],
)
t = s.apply_async()
r = t.get()
assert r == 'foo'
def test_gift(
init_database,
default_chain_spec,
contract_roles,
agent_roles,
account_registry,
faucet,
eth_rpc,
eth_signer,
init_celery_tasks,
cic_registry,
celery_session_worker,
):
nonce_oracle = RPCNonceOracle(contract_roles['ACCOUNT_REGISTRY_WRITER'], eth_rpc)
c = AccountRegistry(signer=eth_signer, nonce_oracle=nonce_oracle, chain_id=default_chain_spec.chain_id())
(tx_hash_hex, o) = c.add(account_registry, contract_roles['ACCOUNT_REGISTRY_WRITER'], agent_roles['ALICE'])
eth_rpc.do(o)
o = receipt(tx_hash_hex)
r = eth_rpc.do(o)
assert r['status'] == 1
s_nonce = celery.signature(
'cic_eth.eth.tx.reserve_nonce',
[
agent_roles['ALICE'],
],
queue=None,
)
s_gift = celery.signature(
'cic_eth.eth.account.gift',
[
default_chain_spec.asdict(),
],
queue=None,
)
s_nonce.link(s_gift)
t = s_nonce.apply_async()
r = t.get_leaf()
assert t.successful()