Lash/abi encoder

This commit is contained in:
Louis Holbrook
2021-04-04 12:55:27 +00:00
parent 1f19aecd0e
commit b3d782b4bd
43 changed files with 2135 additions and 327 deletions

25
tests/conftest.py Normal file
View File

@@ -0,0 +1,25 @@
# standard imports
import os
# external imports
import pytest
from crypto_dev_signer.keystore.dict import DictKeystore
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
@pytest.fixture(scope='session')
def keystore():
ks = DictKeystore()
pk = os.urandom(32)
ks.import_raw_key(pk)
return ks
@pytest.fixture(scope='session')
def signer(
keystore,
):
s = EIP155Signer(keystore)
return s

29
tests/test_abi.py Normal file
View File

@@ -0,0 +1,29 @@
from chainlib.eth.contract import (
ABIContractEncoder,
ABIContractType,
)
def test_abi_param():
e = ABIContractEncoder()
e.uint256(42)
e.bytes32('0x666f6f')
e.address('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef')
e.method('foo')
e.typ(ABIContractType.UINT256)
e.typ(ABIContractType.BYTES32)
e.typ(ABIContractType.ADDRESS)
assert e.types[0] == ABIContractType.UINT256
assert e.types[1] == ABIContractType.BYTES32
assert e.types[2] == ABIContractType.ADDRESS
assert e.contents[0] == '000000000000000000000000000000000000000000000000000000000000002a'
assert e.contents[1] == '0000000000000000000000000000000000000000000000000000000000666f6f'
assert e.contents[2] == '000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef'
assert e.get() == 'a08f54bb000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000666f6f000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef'
if __name__ == '__main__':
test_abi_param()

74
tests/test_erc20.py Normal file
View File

@@ -0,0 +1,74 @@
# standard imports
import logging
import os
# external imports
from hexathon import (
strip_0x,
add_0x,
)
# local imports
from chainlib.eth.erc20 import ERC20
from chainlib.eth.address import to_checksum_address
from chainlib.eth.tx import (
unpack,
TxFormat,
)
from chainlib.eth.pytest import *
logg = logging.getLogger()
contract_address = to_checksum_address('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef')
benefactor_address = to_checksum_address('0xefdeadbeefdeadbeefdeadbeefdeadbeefdeadbe')
# TODO: use unittest instead
def test_erc20_balance(
default_chain_spec,
):
e = ERC20(default_chain_spec,)
holder_address = to_checksum_address('0xbeefdeadbeefdeadbeefdeadbeefdeadbeefdead')
o = e.balance_of(contract_address, holder_address)
assert len(o['params'][0]['data']) == 64 + 8 + 2
assert o['params'][0]['data'][:10] == add_0x('70a08231')
def test_erc20_decimals(
default_chain_spec,
):
e = ERC20(default_chain_spec)
o = e.decimals(contract_address)
assert o['params'][0]['data'] == add_0x('313ce567')
def test_erc20_transfer(
keystore,
signer,
default_chain_spec,
):
e = ERC20(default_chain_spec, signer=signer)
addresses = keystore.list()
(tx_hash_hex, o) = e.transfer(contract_address, addresses[0], benefactor_address, 1024)
def test_erc20_parse_transfer_request(
keystore,
signer,
default_chain_spec,
):
e = ERC20(default_chain_spec, signer=signer)
addresses = keystore.list()
(tx_hash_hex, o) = e.transfer(contract_address, addresses[0], benefactor_address, 1024, tx_format=TxFormat.RLP_SIGNED)
b = bytes.fromhex(strip_0x(o))
#chain_spec = ChainSpec('evm', 'foo', 1, 'bar')
tx = unpack(b, default_chain_spec)
r = ERC20.parse_transfer_request(tx['data'])
assert r[0] == benefactor_address
assert r[1] == 1024

26
tests/test_nonce.py Normal file
View File

@@ -0,0 +1,26 @@
# standard imports
import os
import unittest
# local imports
from chainlib.eth.address import to_checksum_address
from chainlib.eth.nonce import OverrideNonceOracle
from hexathon import add_0x
# test imports
from tests.base import TestBase
class TestNonce(TestBase):
def test_nonce(self):
addr_bytes = os.urandom(20)
addr = add_0x(to_checksum_address(addr_bytes.hex()))
n = OverrideNonceOracle(addr, 42)
self.assertEqual(n.get_nonce(), 42)
self.assertEqual(n.next_nonce(), 42)
self.assertEqual(n.next_nonce(), 43)
if __name__ == '__main__':
unittest.main()

123
tests/test_sign.py Normal file
View File

@@ -0,0 +1,123 @@
# standard imports
import os
import socket
import unittest
import unittest.mock
import logging
import json
# external imports
from crypto_dev_signer.eth.transaction import EIP155Transaction
from crypto_dev_signer.eth.signer.defaultsigner import ReferenceSigner
from crypto_dev_signer.keystore.dict import DictKeystore
# local imports
import chainlib
from chainlib.eth.connection import EthUnixSignerConnection
from chainlib.eth.sign import sign_transaction
from chainlib.eth.tx import TxFactory
from chainlib.eth.address import to_checksum_address
from chainlib.jsonrpc import (
jsonrpc_response,
jsonrpc_error,
)
from hexathon import (
add_0x,
)
from chainlib.chain import ChainSpec
from tests.base import TestBase
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
keystore = DictKeystore()
alice = keystore.new()
bob = keystore.new()
class Mocket(socket.socket):
req_id = None
error = False
tx = None
signer = None
def connect(self, v):
return self
def send(self, v):
o = json.loads(v)
logg.debug('mocket received {}'.format(v))
Mocket.req_id = o['id']
params = o['params'][0]
if to_checksum_address(params.get('from')) != alice:
logg.error('from does not match alice {}'.format(params))
Mocket.error = True
if to_checksum_address(params.get('to')) != bob:
logg.error('to does not match bob {}'.format(params))
Mocket.error = True
if not Mocket.error:
Mocket.tx = EIP155Transaction(params, params['nonce'], params['chainId'])
logg.debug('mocket {}'.format(Mocket.tx))
return len(v)
def recv(self, c):
if Mocket.req_id != None:
o = None
if Mocket.error:
o = jsonrpc_error(Mocket.req_id)
else:
tx = Mocket.tx
r = Mocket.signer.sign_transaction_to_rlp(tx)
#mock_sig = os.urandom(64)
#tx.r = mock_sig[:32]
#tx.s = mock_sig[32:]
#r = add_0x(tx.rlp_serialize().hex())
Mocket.tx = None
o = jsonrpc_response(Mocket.req_id, add_0x(r.hex()))
Mocket.req_id = None
return json.dumps(o).encode('utf-8')
return b''
class TestSign(TestBase):
def setUp(self):
super(TestSign, self).__init__()
self.chain_spec = ChainSpec('evm', 'foo', 42)
logg.debug('alice {}'.format(alice))
logg.debug('bob {}'.format(bob))
self.signer = ReferenceSigner(keystore)
Mocket.signer = self.signer
def test_sign_build(self):
with unittest.mock.patch('chainlib.connection.socket.socket', Mocket) as m:
rpc = EthUnixSignerConnection('foo', chain_spec=self.chain_spec)
f = TxFactory(self.chain_spec, signer=rpc)
tx = f.template(alice, bob, use_nonce=True)
tx = f.build(tx)
logg.debug('tx result {}'.format(tx))
def test_sign_rpc(self):
with unittest.mock.patch('chainlib.connection.socket.socket', Mocket) as m:
rpc = EthUnixSignerConnection('foo')
f = TxFactory(self.chain_spec, signer=rpc)
tx = f.template(alice, bob, use_nonce=True)
tx_o = sign_transaction(tx)
rpc.do(tx_o)
if __name__ == '__main__':
unittest.main()

30
tests/test_tx.py Normal file
View File

@@ -0,0 +1,30 @@
# standard imports
import unittest
# local imports
from chainlib.eth.unittest.ethtester import EthTesterCase
from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.gas import (
RPCGasOracle,
Gas,
)
from chainlib.eth.tx import (
unpack,
TxFormat,
)
from hexathon import strip_0x
class TxTestCase(EthTesterCase):
def test_tx_reciprocal(self):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
gas_oracle = RPCGasOracle(self.rpc)
c = Gas(signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_spec=self.chain_spec)
(tx_hash_hex, o) = c.create(self.accounts[0], self.accounts[1], 1024, tx_format=TxFormat.RLP_SIGNED)
tx = unpack(bytes.fromhex(strip_0x(o)), self.chain_spec)
self.assertEqual(tx['from'], self.accounts[0])
self.assertEqual(tx['to'], self.accounts[1])
if __name__ == '__main__':
unittest.main()