Skip to content

Commit

Permalink
Fix signing of gravity batches (#966)
Browse files Browse the repository at this point in the history
* Fix signing of gravity batches

This was put off because I didn't fully understand how Compass hashed
batches before comparing signatures.  Now, I've come back to this and
fixed it to sign exactly like Compass expects.

The test used here is using a real example, to ensure it works exactly
as expected.

* remove commented out code

---------

Co-authored-by: Tyler Ruppert <{ID}+{username}@users.noreply.github.com>
  • Loading branch information
ToasterTheBrave and Tyler Ruppert authored Sep 1, 2023
1 parent 96698d6 commit 5d41df2
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 59 deletions.
14 changes: 6 additions & 8 deletions x/gravity/types/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,13 @@ func (i InternalOutgoingTxBatch) GetCheckpoint(turnstoneID string) ([]byte, erro
{Type: whoops.Must(abi.NewType("bytes32", "", nil))},
// deadline
{Type: whoops.Must(abi.NewType("uint256", "", nil))},
// methodName
{Type: whoops.Must(abi.NewType("bytes32", "", nil))},
}

var turnstoneBytes32 [32]byte
copy(turnstoneBytes32[:], turnstoneID)

method := abi.NewMethod("batch_call", "batch_call", abi.Function, "", false, false, arguments, abi.Arguments{})

methodNameBytes := []uint8("batch_call")
var batchMethodName [32]uint8
copy(batchMethodName[:], methodNameBytes)
Expand All @@ -257,7 +257,7 @@ func (i InternalOutgoingTxBatch) GetCheckpoint(turnstoneID string) ([]byte, erro
}

args := struct {
Receiver []gethcommon.Address `json:"receiver"`
Receiver []gethcommon.Address
Amount []*big.Int
}{
Receiver: txDestinations,
Expand All @@ -270,16 +270,14 @@ func (i InternalOutgoingTxBatch) GetCheckpoint(turnstoneID string) ([]byte, erro
big.NewInt(int64(i.BatchNonce)),
turnstoneBytes32,
big.NewInt(int64(i.BatchTimeout)),
batchMethodName,
)
// this should never happen outside of test since any case that could crash on encoding
// should be filtered above.
if err != nil {
return nil, sdkerrors.Wrap(err, fmt.Sprintf("Error packing checkpoint! %s/n", err))
}

// we hash the resulting encoded bytes discarding the first 4 bytes these 4 bytes are the constant
// method name 'checkpoint'. If you were to replace the checkpoint constant in this code you would
// then need to adjust how many bytes you truncate off the front to get the output of abi.encode()
return crypto.Keccak256Hash(abiEncodedBatch[4:]).Bytes(), nil
abiEncodedBatch = append(method.ID[:], abiEncodedBatch...)

return crypto.Keccak256(abiEncodedBatch), nil
}
94 changes: 43 additions & 51 deletions x/gravity/types/batch_test.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,45 @@
package types

//// TODO: making these test work (with a new hash from compass) will prove useful
//
//import (
// "encoding/hex"
// "testing"
//
// sdk "github.com/cosmos/cosmos-sdk/types"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/require"
//)
//
//// TODO : Come back and fix this test once I have checkpointing done
//// TestOutgoingTxBatchCheckpointGold1 tests an outgoing tx batch checkpoint
//// nolint: exhaustruct
//func TestOutgoingTxBatchCheckpoint(t *testing.T) {
// senderAddr, err := sdk.AccAddressFromHexUnsafe("527FBEE652609AB150F0AEE9D61A2F76CFC4A73E")
// require.NoError(t, err)
// var (
// erc20Addr = "0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e"
// )
// erc20Address, err := NewEthAddress(erc20Addr)
// require.NoError(t, err)
// destAddress, err := NewEthAddress("0x9FC9C2DfBA3b6cF204C37a5F690619772b926e39")
// require.NoError(t, err)
// src := OutgoingTxBatch{
// BatchNonce: 1,
// BatchTimeout: 2111,
// Transactions: []OutgoingTransferTx{
// {
// Id: 0x1,
// Sender: senderAddr.String(),
// DestAddress: destAddress.GetAddress().Hex(),
// Erc20Token: ERC20Token{
// Amount: sdk.NewInt(0x1),
// Contract: erc20Address.GetAddress().Hex(),
// ChainReferenceId: "test-chain",
// },
// },
// },
// TokenContract: erc20Address.GetAddress().Hex(),
// }
//
// ourHash := src.GetCheckpoint("foo")
//
// // hash from bridge contract
// goldHash := "0xa3a7ee0a363b8ad2514e7ee8f110d7449c0d88f3b0913c28c1751e6e0079a9b2"[2:]
// // The function used to compute the "gold hash" above is in /solidity/test/updateValsetAndSubmitBatch.ts
// // Be aware that every time that you run the above .ts file, it will use a different tokenContractAddress and thus compute
// // a different hash.
// assert.Equal(t, goldHash, hex.EncodeToString(ourHash))
//}
import (
"encoding/hex"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// TestOutgoingTxBatchCheckpointGold1 tests an outgoing tx batch checkpoint
// nolint: exhaustruct
func TestOutgoingTxBatchCheckpoint(t *testing.T) {
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("paloma", "pub")
config.SetBech32PrefixForValidator("palomavaloper", "valoperpub")

src := OutgoingTxBatch{
BatchNonce: 10,
BatchTimeout: 1693598120,
Transactions: []OutgoingTransferTx{
{
Id: 4,
Sender: "paloma1rxdhpk85wju9z9kqf6m0wq0rkty7gpjhey4wd2",
DestAddress: "0xE3cD54d29CBf35648EDcf53D6a344bd4B88DA059",
Erc20Token: ERC20Token{
Amount: sdk.NewInt(10000000),
Contract: "0x28E9e9bfedEd29747FCc33ccA25b4B75f05E434B",
ChainReferenceId: "bnb-main",
},
},
},
TokenContract: "0x28E9e9bfedEd29747FCc33ccA25b4B75f05E434B",
}

actualHash, err := src.GetCheckpoint("5270")
require.NoError(t, err)

actualHashHex := hex.EncodeToString(actualHash)
// hash from bridge contract
expectedHash := "0xcab79faf47d1556c5b273afb063ab1889461e35bc6403e410af240cefdb0fd8e"[2:]

assert.Equal(t, expectedHash, actualHashHex)
}

0 comments on commit 5d41df2

Please sign in to comment.