commit b9788adb1855a21f50bbfd4ac90693aca96533fe
parent 494cb1e0aff331bbfdfae5e99c4b269aa3d6d60c
Author: nolash <dev@holbrook.no>
Date: Sat, 12 Jun 2021 21:42:04 +0200
Add tx reverse re-pack
Diffstat:
4 files changed, 80 insertions(+), 6 deletions(-)
diff --git a/chainlib/eth/tx.py b/chainlib/eth/tx.py
@@ -14,6 +14,7 @@ from rlp import decode as rlp_decode
from rlp import encode as rlp_encode
from crypto_dev_signer.eth.transaction import EIP155Transaction
from crypto_dev_signer.encoding import public_key_to_address
+from crypto_dev_signer.eth.encoding import chain_id_to_v
from potaahto.symbols import snake_and_camel
@@ -71,6 +72,25 @@ def count_confirmed(address):
return count(address, True)
+def pack(tx_src, chain_spec):
+ if isinstance(tx_src, Tx):
+ tx_src = tx_src.as_dict()
+ tx = EIP155Transaction(tx_src, tx_src['nonce'], chain_spec.chain_id())
+
+ signature = bytearray(65)
+ cursor = 0
+ for a in [
+ tx_src['r'],
+ tx_src['s'],
+ ]:
+ for b in bytes.fromhex(strip_0x(a)):
+ signature[cursor] = b
+ cursor += 1
+ signature[cursor] = tx_src['v']
+ tx.apply_signature(chain_spec.chain_id(), signature, literal_v=True)
+ return tx.rlp_serialize()
+
+
def unpack(tx_raw_bytes, chain_spec):
chain_id = chain_spec.chain_id()
tx = __unpack_raw(tx_raw_bytes, chain_id)
@@ -154,10 +174,11 @@ def __unpack_raw(tx_raw_bytes, chain_id=1):
'gas': d[2],
'value': d[4],
'data': data,
- 'v': chain_id,
+ 'v': v,
+ 'recovery_byte': vb,
'r': add_0x(sig[:32].hex()),
's': add_0x(sig[32:64].hex()),
- 'chainId': chain_id,
+ 'chainId': vb, #chain_id,
'hash': add_0x(signed_hash.hex()),
'hash_unsigned': add_0x(unsigned_hash.hex()),
}
@@ -377,6 +398,10 @@ class Tx:
return snake_and_camel(src)
+ def as_dict(self):
+ return self.src
+
+
def apply_receipt(self, rcpt):
rcpt = self.src_normalize(rcpt)
logg.debug('rcpt {}'.format(rcpt))
diff --git a/requirements.txt b/requirements.txt
@@ -1,4 +1,4 @@
-crypto-dev-signer~=0.4.14b3
+crypto-dev-signer~=0.4.14b5
pysha3==1.0.2
hexathon~=0.0.1a7
websocket-client==0.57.0
diff --git a/setup.cfg b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = chainlib
-version = 0.0.3rc3
+version = 0.0.3rc4
description = Generic blockchain access library and tooling
author = Louis Holbrook
author_email = dev@holbrook.no
diff --git a/tests/test_tx.py b/tests/test_tx.py
@@ -1,5 +1,7 @@
# standard imports
-import unittest
+import os
+import unittest
+import logging
# local imports
from chainlib.eth.unittest.ethtester import EthTesterCase
@@ -10,9 +12,26 @@ from chainlib.eth.gas import (
)
from chainlib.eth.tx import (
unpack,
+ pack,
+ raw,
+ transaction,
TxFormat,
+ TxFactory,
+ Tx,
)
-from hexathon import strip_0x
+from chainlib.eth.contract import (
+ ABIContractEncoder,
+ ABIContractType,
+ )
+from chainlib.eth.address import to_checksum_address
+from hexathon import (
+ strip_0x,
+ add_0x,
+ )
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
class TxTestCase(EthTesterCase):
@@ -26,5 +45,35 @@ class TxTestCase(EthTesterCase):
self.assertEqual(tx['to'], self.accounts[1])
+ def test_tx_pack(self):
+ nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
+ gas_oracle = RPCGasOracle(self.rpc)
+
+ mock_contract = to_checksum_address(add_0x(os.urandom(20).hex()))
+
+ f = TxFactory(self.chain_spec, signer=self.rpc)
+ enc = ABIContractEncoder()
+ enc.method('fooMethod')
+ enc.typ(ABIContractType.UINT256)
+ enc.uint256(13)
+ data = enc.get()
+ tx = f.template(self.accounts[0], mock_contract, use_nonce=True)
+ tx = f.set_code(tx, data)
+ (tx_hash, tx_signed_raw_hex) = f.finalize(tx, TxFormat.RLP_SIGNED)
+ logg.debug('tx result {}'.format(tx))
+ o = raw(tx_signed_raw_hex)
+ r = self.rpc.do(o)
+ o = transaction(tx_hash)
+ tx_rpc_src = self.rpc.do(o)
+ logg.debug('rpc src {}'.format(tx_rpc_src))
+
+ tx_signed_raw_bytes = bytes.fromhex(strip_0x(tx_signed_raw_hex))
+ tx_src = unpack(tx_signed_raw_bytes, self.chain_spec)
+ txo = Tx(tx_src)
+ tx_signed_raw_bytes_recovered = pack(txo, self.chain_spec)
+ logg.debug('o {}'.format(tx_signed_raw_bytes.hex()))
+ logg.debug('r {}'.format(tx_signed_raw_bytes_recovered.hex()))
+ self.assertEqual(tx_signed_raw_bytes, tx_signed_raw_bytes_recovered)
+
if __name__ == '__main__':
unittest.main()