Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-712: Array support #22

Closed
wants to merge 2 commits into from
Closed

EIP-712: Array support #22

wants to merge 2 commits into from

Conversation

bitpshr
Copy link
Contributor

@bitpshr bitpshr commented Jul 15, 2018

The original implementation of signTypedData omitted array support. This pull request remedies this by adding array support as per EIP-712 along with updated tests.

@bitpshr bitpshr requested a review from danfinlay July 15, 2018 04:36
@@ -318,17 +318,17 @@ test('signedTypeData', (t) => {
const sig = sigUtil.signTypedData(privateKey, { data: typedData })

t.equal(utils.encodeType('Mail', typedData.types),
'Mail(Person from,Person to,string contents)Person(string name,address wallet)')
'Mail(Person from,Person[] to,string contents)Person(string name,address wallet)')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend adding an independent test for this, to avoid changing the test values provided in the EIP, this way it is also ensured that the previous behaviour did not break.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rmeissner, thanks for the feedback. I submitted an upstream PR to update the EIP test values (see ethereum/EIPs#1242.) While we don't plan to land this PR until that upstream PR also lands, you're right that separate tests would be more robust. Will update.

@@ -16,7 +16,7 @@ const typedData = {
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'to', type: 'Person[]' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when creating the typeHash a lookup is performed based on the type. In this case the type would be Person[], so it would not match Person in the types dictionary.

In the test this works since from references Person, but would be interesting if it still works when we remove that reference.

t.equal(ethUtil.bufferToHex(utils.encodeData(typedData.primaryType, typedData.message, typedData.types)),
'0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8')
'0xdd57d9596af52b430ced3d5b52d4e3d5dccfdf3e0572db1dcf526baad311fbd1fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c872ea07cf404427eb52aed74d9998e238434f046d95c4ff7802d628628bf77a16b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When implementing this in python it seems like that these test values are wrong.

To verify this I created a smart contract on remix:

pragma solidity 0.4.24;

contract Test {
    
    function personData()
        public
        pure
        returns (bytes) 
    {
        bytes32 personSchemaHash = keccak256("Person(string name,address wallet)");
        return abi.encode(
            personSchemaHash,
            keccak256('Bob'),
            address(0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB)
        );
    }
    
    function signData()
        public
        pure
        returns (bytes) 
    {
        bytes32 personSchemaHash = keccak256("Person(string name,address wallet)");
        return abi.encode(
            0xdd57d9596af52b430ced3d5b52d4e3d5dccfdf3e0572db1dcf526baad311fbd1,
            keccak256(
                abi.encode(
                    personSchemaHash,
                    keccak256('Cow'),
                    address(0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826)
                )
            ),
            keccak256(personData()),
            keccak256("Hello, Bob!")
        );
    }
    
    function signHash()
        public
        pure
        returns (bytes32) 
    {
        return keccak256(signData());
    }
    
    function sign()
        public
        pure
        returns (bytes32) 
    {
        return keccak256(abi.encodePacked(
            byte(0x19), 
            byte(1), 
            0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f, 
            signHash()
        ));
    }
}

The issue seems to be in the code where the array data is concatenated (see comment above)

throw new Error('Arrays currently unimplemented in encodeData')
encodedTypes.push('bytes32')
const parsedType = field.type.slice(0, field.type.lastIndexOf('['))
value = ethUtil.sha3(value.map(item => this.encodeData(parsedType, item, types)).join(''))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seems that join converts this into a string and result in a wrong hash (see comment in tests)

To fix this use:
Buffer.concat(value.map(item => this.encodeData(parsedType, item, types)))

Copy link
Contributor

@danfinlay danfinlay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see the comments posted by rmeissner addressed before merging.

@bitpshr
Copy link
Contributor Author

bitpshr commented Sep 10, 2018

Closing this for now and will re-open when EIP-712 array support firms up. Per the proposal's author:

In the screencast I see that arrays are implemented. This is still somewhat subject to change in EIP712. What I think will happen is that EIP712 will follow whatever encoding Solidity uses internally in memory and/or what ABIv2 uses. This may or may not be the same as what is currently specified. If there is a change, I expect it will be in the handling of fixed size arrays.

@bitpshr bitpshr closed this Sep 10, 2018
@whymarrh whymarrh deleted the signed-arrays branch January 23, 2020 02:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants