Ejemplo n.º 1
0
def test_default_domain(default_domain_manager):
    assert eip712_structs.default_domain is None

    class Foo(EIP712Struct):
        s = String()

    foo = Foo(s='hello world')

    domain = make_domain(name='domain')
    other_domain = make_domain(name='other domain')

    # When neither methods provide a domain, expect a ValueError
    with pytest.raises(ValueError, match='Domain must be provided'):
        foo.to_message()
    with pytest.raises(ValueError, match='Domain must be provided'):
        foo.signable_bytes()

    # But we can still provide a domain explicitly
    explicit_msg = foo.to_message(domain)
    explicit_bytes = foo.signable_bytes(domain)

    # Setting it lets us forgo providing it
    eip712_structs.default_domain = domain
    implicit_msg = foo.to_message()
    implicit_bytes = foo.signable_bytes()

    # Either method should produce the same result
    assert implicit_msg == explicit_msg
    assert implicit_bytes == explicit_bytes

    # Using a different domain should not use any current default domain
    assert implicit_msg != foo.to_message(other_domain)
    assert implicit_bytes != foo.signable_bytes(other_domain)
Ejemplo n.º 2
0
def test_domain_sep_create():
    salt = os.urandom(32)
    domain_struct = make_domain(name='name', salt=salt)

    expected_result = 'EIP712Domain(string name,bytes32 salt)'
    assert domain_struct.encode_type() == expected_result

    expected_data = b''.join([keccak(text='name'), salt])
    assert domain_struct.encode_value() == expected_data

    with pytest.raises(ValueError,
                       match='At least one argument must be given'):
        make_domain()
Ejemplo n.º 3
0
def hash_struct(tx, domain=None, verifyingContract=None):
    if domain and verifyingContract:
        raise RuntimeError("verifyingContract supplied but ignored")

    verifying_address = verifyingContract.address if verifyingContract else NULL_ADDRESS

    inputs = [
        Input(blknum=i.blknum, txindex=i.txindex, oindex=i.oindex)
        for i in tx.inputs
    ]
    outputs = [
        Output(owner=o.output_guard, currency=o.token, amount=o.amount)
        for o in tx.outputs
    ]

    domain = domain or make_domain(
        name='OMG Network',
        version='1',
        verifyingContract=verifying_address,
        salt=bytes.fromhex(
            'fad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83')
    )

    type = Transaction().encode_type() + Input.encode_type(
    ) + Output.encode_type()
    values = [_hash_typed(t)
              for t in inputs] + [_hash_typed(t) for t in outputs
                                  ] + [tx.metadata or NULL_HASH]

    return keccak(b'\x19\x01' + _hash_typed(domain) +
                  _hash_struct(type, b''.join(values)))
Ejemplo n.º 4
0
 def build_domain_separator(cls, ethereum_network: EthereumNetwork):
     return make_domain(
         name="Gnosis Protocol",
         version="v2",
         chainId=str(ethereum_network.value),
         verifyingContract=cls.
         settlement_contract_addresses[ethereum_network],
     )
Ejemplo n.º 5
0
def test_signable_bytes():
    class Foo(EIP712Struct):
        s = String()
        i = Int(256)

    domain = make_domain(name='hello')
    foo = Foo(s='hello', i=1234)

    start_bytes = b'\x19\x01'
    exp_domain_bytes = keccak(domain.type_hash() + domain.encode_value())
    exp_struct_bytes = keccak(foo.type_hash() + foo.encode_value())

    sign_bytes = foo.signable_bytes(domain)
    assert sign_bytes[0:2] == start_bytes
    assert sign_bytes[2:34] == exp_domain_bytes
    assert sign_bytes[34:] == exp_struct_bytes
def hash_struct(tx, domain=None, verifying_contract=None):
    if domain and verifying_contract:
        raise RuntimeError("verifyingContract supplied but ignored")

    verifying_address = hex_to_binary(
        verifying_contract.address) if verifying_contract else NULL_ADDRESS

    domain = domain or make_domain(
        name='OMG Network',
        version='1',
        verifyingContract=verifying_address,
        salt=hex_to_binary(
            'fad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83')
    )

    return keccak(b'\x19\x01' + domain.hash_struct() +
                  struct_tx_from_tx(tx).hash_struct())
Ejemplo n.º 7
0
def test_flat_struct_to_message():
    class Foo(EIP712Struct):
        s = String()

    domain = make_domain(name='domain')
    foo = Foo(s='foobar')

    expected_result = {
        'primaryType': 'Foo',
        'types': {
            'EIP712Domain': [{
                'name': 'name',
                'type': 'string',
            }],
            'Foo': [{
                'name': 's',
                'type': 'string',
            }]
        },
        'domain': {
            'name': 'domain',
        },
        'message': {
            's': 'foobar'
        }
    }

    message = foo.to_message(domain)
    assert message == expected_result

    # Now test in reverse...
    new_struct, domain = EIP712Struct.from_message(expected_result)
    assert new_struct.type_name == 'Foo'

    members_list = new_struct.get_members()
    assert len(members_list) == 1
    assert members_list[0][0] == 's'
    assert members_list[0][1].type_name == 'string'

    assert new_struct['s'] == 'foobar'
Ejemplo n.º 8
0
def test_domain_sep_types():
    salt = os.urandom(32)
    contract = os.urandom(20)

    domain_struct = make_domain(name='name',
                                version='version',
                                chainId=1,
                                verifyingContract=contract,
                                salt=salt)

    encoded_data = [
        keccak(text='name'),
        keccak(text='version'),
        int(1).to_bytes(32, 'big', signed=False),
        bytes(12) + contract, salt
    ]

    expected_result = 'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)'
    assert domain_struct.encode_type() == expected_result

    expected_data = b''.join(encoded_data)
    assert domain_struct.encode_value() == expected_data
Ejemplo n.º 9
0
 def _eip712_payload(self) -> StructTuple:
     data = self.data.hex() if self.data else ""
     safe_version = Version(self.safe_version)
     cls = EIP712SafeTx if safe_version >= Version(
         "1.0.0") else EIP712LegacySafeTx
     message = cls(
         to=self.to,
         value=self.value,
         data=data,
         operation=self.operation,
         safeTxGas=self.safe_tx_gas,
         baseGas=self.base_gas,
         dataGas=self.base_gas,
         gasPrice=self.gas_price,
         gasToken=self.gas_token,
         refundReceiver=self.refund_receiver,
         nonce=self.safe_nonce,
     )
     domain = make_domain(
         verifyingContract=self.safe_address,
         chainId=self.chain_id
         if safe_version >= Version("1.3.0") else None,
     )
     return StructTuple(message, domain)
Ejemplo n.º 10
0
def test_bytes_json_encoder():
    class Foo(EIP712Struct):
        b = Bytes(32)
    domain = make_domain(name='domain')

    bytes_val = os.urandom(32)
    foo = Foo(b=bytes_val)
    result = foo.to_message_json(domain)

    expected_substring = f'"b": "0x{bytes_val.hex()}"'
    assert expected_substring in result

    reconstructed = EIP712Struct.from_message(json.loads(result))
    assert reconstructed.domain == domain
    assert reconstructed.message == foo

    class UnserializableObject:
        pass
    obj = UnserializableObject()

    # Fabricate this failure case to test that the custom json encoder's fallback path works as expected.
    foo.values['b'] = obj
    with pytest.raises(TypeError, match='not JSON serializable'):
        foo.to_message_json(domain)
import pytest

from plasma_core.constants import NULL_ADDRESS
from plasma_core.transaction import Transaction
from eip712_structs import make_domain
from plasma_core.utils.eip712_struct_hash import hash_struct


verifyingContract = bytes.fromhex('44de0ec539b8c4a4b530c78620fe8320167f2f74')
test_domain = make_domain(
    name='OMG Network',
    version='1',
    verifyingContract=verifyingContract,
    salt=bytes.fromhex('fad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83')
)
owner = bytes.fromhex('2258a5279850f6fb78888a7e45ea2a5eb1b3c436')
token = bytes.fromhex('0123456789abcdef000000000000000000000000')

metadata = bytes.fromhex('853a8d8af99c93405a791b97d57e819e538b06ffaa32ad70da2582500bc18d43')

inputs = [
    (1, 0, 0),
    (1000, 2, 3),
    (101000, 1337, 3)
]
outputs = [
    (owner, NULL_ADDRESS, 100),
    (token, NULL_ADDRESS, 111),
    (owner, token, 1337)
]
Ejemplo n.º 12
0
from plasma_core.constants import NULL_ADDRESS
from plasma_core.transaction import Transaction
from eip712_structs import make_domain
from plasma_core.utils.eip712_struct_hash import hash_struct

# TODO: Run the tests on new tx format
#  Metamask currently does not implement dynamic arrays

pytestmark = pytest.mark.skip(
    reason="Dynamic arrays and optional fields in tx format")

test_domain = make_domain(
    name='OMG Network',
    version='1',
    verifyingContract=bytes.fromhex(
        '44de0ec539b8c4a4b530c78620fe8320167f2f74'),
    salt=bytes.fromhex(
        'fad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83'))
owner = bytes.fromhex('2258a5279850f6fb78888a7e45ea2a5eb1b3c436')
token = bytes.fromhex('0123456789abcdef000000000000000000000000')

metadata = bytes.fromhex(
    '853a8d8af99c93405a791b97d57e819e538b06ffaa32ad70da2582500bc18d43')

inputs = [(1, 0, 0), (1000, 2, 3), (101000, 1337, 3)]
outputs = [(owner, NULL_ADDRESS, 100), (token, NULL_ADDRESS, 111),
           (owner, token, 1337)]


# NOTE: following test vectors were confirmed against contracts code
Ejemplo n.º 13
0
def test_nested_struct_to_message():
    class Bar(EIP712Struct):
        s = String()

    class Foo(EIP712Struct):
        s = String()
        bar = Bar

    domain = make_domain(name='domain')

    foo = Foo(
        s="foo",
        bar=Bar(s="bar")
    )

    expected_result = {
        'primaryType': 'Foo',
        'types': {
            'EIP712Domain': [{
                'name': 'name',
                'type': 'string',
            }],
            'Foo': [{
                'name': 's',
                'type': 'string',
            }, {
                'name': 'bar',
                'type': 'Bar',
            }],
            'Bar': [{
                'name': 's',
                'type': 'string',
            }]
        },
        'domain': {
            'name': 'domain',
        },
        'message': {
            's': 'foo',
            'bar': {
                's': 'bar',
            }
        }
    }

    message = foo.to_message(domain)
    assert message == expected_result

    # And test in reverse...
    new_struct, new_domain = EIP712Struct.from_message(expected_result)
    assert new_struct.type_name == 'Foo'

    members = new_struct.get_members()
    assert len(members) == 2
    assert members[0][0] == 's' and members[0][1].type_name == 'string'
    assert members[1][0] == 'bar' and members[1][1].type_name == 'Bar'

    bar_val = new_struct['bar']
    assert bar_val.type_name == 'Bar'
    assert bar_val['s'] == 'bar'

    assert foo.hash_struct() == new_struct.hash_struct()