Add a builtin for decoding TokenMessage for hyperlane SPI#1344
Add a builtin for decoding TokenMessage for hyperlane SPI#1344
Conversation
edmundnoble
left a comment
There was a problem hiding this comment.
My approval is waiting on @AK3N's
pact.cabal
Outdated
| , base >= 4.18.0.0 | ||
| , base16-bytestring >=0.1.1.6 | ||
| , base64-bytestring >=1.0.0.1 | ||
| , binary |
src/Pact/Native.hs
Outdated
|
|
||
| -- Parse the size of the following amount field. | ||
| amountSize <- fromIntegral @Word256 @Int <$> getWord256be | ||
| unless (amountSize == 96) |
There was a problem hiding this comment.
That's not an amountSize but the offset of the recipient which is a string.
recipient is a first field of the TokenMessageERC20 structure and since it was encoded with abi.encode there is an offset:
0000000000000000000000000000000000000000000000000000000000000060 # offset of the recipient string = 96, because first three lines are 32 bytes each
0000000000000000000000000000000000000000000000008ac7230489e80000 # amount = 10000000000000000000
0000000000000000000000000000000000000000000000000000000000000000 # chainId = 0
000000000000000000000000000000000000000000000000000000000000002a # recipientSize = 42
3078373143373635364543376162383862303938646566423735314237343031 # "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
4235663664383937364600000000000000000000000000000000000000000000
Let's leave this comment in the code
There was a problem hiding this comment.
@AK3N Thanks for the comment example! The only part I don't understand is the example recipient "0x71C7656EC7ab88b098defB751B7401B5f6d8976F". Our recipients are now JSON-encoded guards, e.g. { "pred": "keys-any", "keys": [...] }. Should we replace the hex string with that?
|
|
||
| pact411Natives :: [Text] | ||
| pact411Natives = ["enforce-verifier", "hyperlane-message-id"] | ||
| pact411Natives = ["enforce-verifier", "hyperlane-message-id", "hyperlane-decode-token-message"] |
There was a problem hiding this comment.
Either we need to specify the version hyperlane-v3-decode-token-message or pass an object with {"version": 3, ...} field.
@edmundnoble, should we also specify the type of the token? hyperlane-decode-token-message-erc20.
There was a problem hiding this comment.
I don't think that's necessary, because tokenmessage is not actually part of the Hyperlane spec, so it's not versioned with it. We can make future versions, if they're needed, use -v2, -v3, etc.
src/Pact/Native.hs
Outdated
|
|
||
| -- Parse the size of the following amount field. | ||
| amountSize <- fromIntegral @Word256 @Int <$> getWord256be | ||
| unless (amountSize == 96) |
There was a problem hiding this comment.
That's not an amountSize but the offset of the recipient which is a string.
recipient is a first field of the TokenMessageERC20 structure and since it was encoded with abi.encode there is an offset:
0000000000000000000000000000000000000000000000000000000000000060 # offset of the recipient string = 96, because first three lines are 32 bytes each
0000000000000000000000000000000000000000000000008ac7230489e80000 # amount = 10000000000000000000
0000000000000000000000000000000000000000000000000000000000000000 # chainId = 0
000000000000000000000000000000000000000000000000000000000000002a # recipientSize = 42
3078373143373635364543376162383862303938646566423735314237343031 # "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
4235663664383937364600000000000000000000000000000000000000000000
Let's leave this comment in the code
src/Pact/Native.hs
Outdated
| where | ||
| getWord256be = get @Word256 | ||
|
|
||
| -- TODO: We check the size. Is this ok? |
There was a problem hiding this comment.
This is good 👍
But my comment was about the take and fromIntegral functions since size :: Word256 and we convert it to Int.
* Add hyperlane-decode-token-message with gas * include chainid in TokenMessage encoding * add principal check for recipient * TokenMessage recipient parsed as guard * add new builtin to pact411natives and suppress a debugging error message * exhaust the TokenMessage when parsing * use wide-word instead of doubleword * remove stale TODOs * cleanup more comments * Set the empirically measured cas cost for TokenMessage decoding * fix example in native definition * fix examples * rename builtin to hyperlane-decode-token-message * use base64-unpadded encoding/decoding for tokenmessage * fix gas costing and add gas tests * lower bound for binary dependency * cleanup tokenmessage decoder comments and variable names * remove padding from encoded message in tokenmessage decoding example * gasmodelspec remove buildin from list of gas-untested * update example encoding
Part of the SPI interface is a
TokenMessage: a tuple of a recipient, and amount, and a chain id:The wire format for a
TokenMessageis a packed binary encoding of these fields, followed by base64url encoding.Pact needs to provide a builtin for decoding such an encoded message into its original form, to support the larger SPI scheme. This PR implements that builtin, named
hyperlane-decode-token-message. It also provides a convenience function for encoding aTokenMessage, useful for testing.Usage:
Todo:
Gas analysis:
The following code was used to benchmark decoding:
The results are: 2 microseconds for a 256-byte message, 11 microseconds for an 10880-byte message, 21 microseconds for a 21548-byte message.
400 MilliGas = 1 microsecond by policy. 10k bytes = 10 microseconds by benchmarks. 100 bytes = 0.1 microseconds = 40 MilliGas. We round up to 50 MilliGas as a safety buffer.
PR checklist:
cabal run tests. If they pass locally, docs are generated.pact -t), make sure pact-lsp is in sync.Additionally, please justify why you should or should not do the following: