Skip to content

Commit

Permalink
Sui move implementation of Axelar cross-chain gateway protocol (#13142)
Browse files Browse the repository at this point in the history
## Description 

Describe the changes or additions included in this PR.

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: Damir Shamanaev <[email protected]>
  • Loading branch information
patrickkuo and damirka authored Sep 18, 2023
1 parent 2f5cf58 commit c06e765
Show file tree
Hide file tree
Showing 10 changed files with 1,490 additions and 0 deletions.
5 changes: 5 additions & 0 deletions crates/sui-axelar-cgp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Axelar cross-chain gateway protocol Sui implementation


## Design
TODO
10 changes: 10 additions & 0 deletions crates/sui-axelar-cgp/move/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "sui-axelar-cgp"
version = "0.0.1"

[dependencies]
Sui = { local= "../../sui-framework/packages/sui-framework" }

[addresses]
axelar = "0x0"
sui = "0x2"
1 change: 1 addition & 0 deletions crates/sui-axelar-cgp/move/presets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
192 changes: 192 additions & 0 deletions crates/sui-axelar-cgp/move/presets/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/**
* This package generates test data for the Axelar
* General Message Passing protocol
*/

const secp256k1 = require("secp256k1");
const {
utils: {keccak256},
} = require("ethers");
const {BCS, fromHEX, toHEX, getSuiMoveConfig} = require("@mysten/bcs");
const bcs = new BCS(getSuiMoveConfig());

// generate privKey
const privKey = Buffer.from(
"9027dcb35b21318572bda38641b394eb33896aa81878a4f0e7066b119a9ea000",
"hex"
);

// get the public key in a compressed format
const pubKey = secp256k1.publicKeyCreate(privKey);

// input argument for the tx
bcs.registerStructType("Input", {
data: "vector<u8>",
proof: "vector<u8>",
});

bcs.registerStructType("Proof", {
// operators is a 33 byte / for now at least
operators: "vector<vector<u8>>",
weights: "vector<u128>",
threshold: "u128",
signatures: "vector<vector<u8>>",
});

// internals of the message
bcs.registerStructType("AxelarMessage", {
chain_id: "u64",
command_ids: "vector<address>",
commands: "vector<string>",
params: "vector<vector<u8>>",
});

// internals of the message
bcs.registerStructType("TransferOperatorshipMessage", {
operators: "vector<vector<u8>>",
weights: "vector<u128>",
threshold: "u128",
});

// defines channel target
bcs.registerStructType("GenericMessage", {
source_chain: "string",
source_address: "string",
target_id: "address",
payload_hash: "vector<u8>",
});

const ZERO_ADDR = "0x".padEnd(62, "0");
const message = bcs
.ser("AxelarMessage", {
chain_id: 1,
command_ids: ["0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002"],
commands: ["approveContractCall", "approveContractCall"],
params: [
bcs
.ser("GenericMessage", {
source_chain: "ETH",
source_address: "0x0",
payload_hash: [0, 0, 0, 0],
target_id: ZERO_ADDR, // using address here for simlicity...
})
.toBytes(),
bcs
.ser("GenericMessage", {
source_chain: "AXELAR",
source_address: "0x1",
payload_hash: [0, 0, 0, 0],
target_id: ZERO_ADDR, // ...
})
.toBytes(),
],
})
.toBytes();

const hashed = fromHEX(hashMessage(message));
const {signature, recid} = secp256k1.ecdsaSign(hashed, privKey);

const proof = bcs
.ser("Proof", {
operators: [pubKey],
weights: [100],
threshold: 10,
signatures: [new Uint8Array([...signature, recid])],
})
.toBytes();

const input = bcs
.ser("Input", {
data: message,
proof: proof,
})
.toString("hex");

console.log("OPERATOR: %s", toHEX(pubKey));
console.log("DATA LENGTH: %d", message.length);
console.log("PROOF LENGTH: %d", proof.length);
console.log("INPUT: %s", input + "00");

// verify the signature // just to make sure that everything is correct on this end
console.log(secp256k1.ecdsaVerify(signature, hashed, pubKey));

{
console.log("*************** TransferOperatorshipMessage ***************");
const message = bcs
.ser("AxelarMessage", {
chain_id: 1,
command_ids: ["0x0000000000000000000000000000000000000000000000000000000000000001"],
commands: ["transferOperatorship"],
params: [
bcs
.ser("TransferOperatorshipMessage", {
operators: [pubKey],
weights: [200],
threshold: 20,
})
.toBytes(),
],
})
.toBytes();

const hashed = fromHEX(hashMessage(message));
const {signature, recid} = secp256k1.ecdsaSign(hashed, privKey);

const proof = bcs
.ser("Proof", {
operators: [pubKey],
weights: [100],
threshold: 10,
signatures: [new Uint8Array([...signature, recid])],
})
.toBytes();

const input = bcs
.ser("Input", {
data: message,
proof: proof,
})
.toString("hex");

console.log("OPERATOR: %s", toHEX(pubKey));
console.log("DATA LENGTH: %d", message.length);
console.log("PROOF LENGTH: %d", proof.length);
console.log("INPUT: %s", input + "00");

// verify the signature // just to make sure that everything is correct on this end
console.log(secp256k1.ecdsaVerify(signature, hashed, pubKey));
}


{
let utf8Encode = new TextEncoder();
let message = utf8Encode.encode("hello world");

const testData = fromHEX(hashMessage(message));
const {recid, signature} = secp256k1.ecdsaSign(testData, privKey);

// don't forget to add '00' to the end of the signature
console.log("message", toHEX(message));
console.log("hashed message", toHEX(testData));
console.log("signature", toHEX(signature) + recid.toString(16).padStart(2, 0));
console.log("recid", recid);
}

/**
* Add a prefix to a message.
* Return resulting array of bytes.
*/
function hashMessage(data) {
// sorry for putting it here...
const messagePrefix = new Uint8Array(
Buffer.from("\x19Sui Signed Message:\n", "ascii")
);
let hashed = new Uint8Array(messagePrefix.length + data.length);
hashed.set(messagePrefix);
hashed.set(data, messagePrefix.length);

return keccak256(hashed);
}
12 changes: 12 additions & 0 deletions crates/sui-axelar-cgp/move/presets/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "axelar-presets",
"version": "1.0.0",
"main": "index.js",
"author": "Damir Shamanaev <[email protected]>",
"license": "MIT",
"dependencies": {
"@mysten/bcs": "^0.5.0",
"ethers": "^5.7.1",
"secp256k1": "^4.0.3"
}
}
Loading

1 comment on commit c06e765

@vercel
Copy link

@vercel vercel bot commented on c06e765 Sep 18, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.