Skip to content

Commit

Permalink
feat: test updateCanonicalChainTx
Browse files Browse the repository at this point in the history
  • Loading branch information
Th0rgal committed Oct 27, 2024
1 parent d9b5055 commit 9962fcf
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 23 deletions.
95 changes: 73 additions & 22 deletions src/UtuProvider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BitcoinProvider } from "./BitcoinProvider";
import { BlockHeightProof, RegisterBlocksTx } from "@/UtuTypes";
import { BlockHeader } from "./BitcoinTypes";
import { byteArray } from "starknet";
import { BigNumberish, byteArray, ByteArray } from "starknet";

const CONTRACT_ADDRESS =
"0x034838129702a2f071cd8cf9277d2f2f2dac3284c2217d9e2e076624fb5afc2f";
Expand All @@ -19,6 +19,51 @@ const serializedHash = (hash: string): string[] => {
.reverse();
};

// Add this helper function near the top with other helpers
const formatFelt = (value: BigNumberish): string => {
if (typeof value === "string" && value.startsWith("0x")) {
return value;
}
return "0x" + (typeof value === "string" ? value : value.toString(16));
};

// Helper function to convert hex string to ByteArray
const byteArrayFromHexString = (hex: string): ByteArray => {
// Remove '0x' prefix if present
hex = hex.replace("0x", "");

const WORD_SIZE = 31; // Maximum bytes per word
const data: BigNumberish[] = [];
let currentWord = "";

// Process pairs of hex chars (1 byte)
for (let i = 0; i < hex.length; i += 2) {
const byte = String.fromCharCode(parseInt(hex.substr(i, 2), 16));
currentWord += byte;

// When we reach WORD_SIZE bytes, add to data array
if (currentWord.length === WORD_SIZE) {
data.push("0x" + Buffer.from(currentWord, "ascii").toString("hex"));
currentWord = "";
}
}

// Handle remaining bytes
if (currentWord.length > 0) {
return {
data,
pending_word: "0x" + Buffer.from(currentWord, "ascii").toString("hex"),
pending_word_len: currentWord.length,
};
}

return {
data,
pending_word: "0x00",
pending_word_len: 0,
};
};

export interface UtuProviderResult {
inclusionProof: string;
bitcoinRelayerTx?: string;
Expand Down Expand Up @@ -123,36 +168,42 @@ export class UtuProvider {
) {
const contractAddress = CONTRACT_ADDRESS;
const selector = "0x...";
const firstBlockHash = await this.bitcoinProvider.getBlockHash(beginHeight);
const lastBlockHash = await this.bitcoinProvider.getBlockHash(endHeight);
const firstBlockHeader = await this.bitcoinProvider.getBlockHeader(
firstBlockHash
);

let calldata = [
"0x" + beginHeight.toString(16),
"0x" + endHeight.toString(16),
formatFelt(beginHeight),
formatFelt(endHeight),
...serializedHash(lastBlockHash),
];

if (proof) {
const proof = await this.getBlockHeightProof(beginHeight);
const rawCoinbaseTx = serializedHash(proof.rawCoinbaseTx);
// Option::Some
calldata.push("0x1");
// rawCoinbaseTx is like a hash but we need to specify its length
calldata.push("0x" + rawCoinbaseTx.length.toString(16), ...rawCoinbaseTx);
calldata.push("0x0");

// block header
calldata.push(...this.serializeBlockHeader(firstBlockHeader));

const byteArrayCoinbaseTx = byteArrayFromHexString(proof.rawCoinbaseTx);

calldata.push(
formatFelt(byteArrayCoinbaseTx.data.length),
...byteArrayCoinbaseTx.data.map((word) => formatFelt(word)),
formatFelt(byteArrayCoinbaseTx.pending_word),
formatFelt(byteArrayCoinbaseTx.pending_word_len)
);
// a merkleProof is basically an array of hashes (fixed size arrays)
calldata.push(
"0x" + proof.merkleProof.length.toString(16),
...proof.merkleProof
.map(byteArray.byteArrayFromString)
.flatMap((byteArr) => [
"0x" + byteArr.data.length.toString(16),
...byteArr.data.map((word) => "0x" + word.toString(16)),
"0x" + byteArr.pending_word.toString(16),
"0x" + byteArr.pending_word_len.toString(16),
])
formatFelt(proof.merkleProof.length),
...proof.merkleProof.flatMap(serializedHash)
);
} else {
// Option::None
calldata.push("0x0");
calldata.push("0x1");
}

return {
Expand All @@ -172,7 +223,7 @@ export class UtuProvider {
selector:
"0x00afd92eeac2cdc892d6323dd051eaf871b8d21df8933ce111c596038eb3afd3",
calldata: [
"0x" + blocks.length.toString(16),
formatFelt(blocks.length),
...blockHeaders.flatMap((header) => this.serializeBlockHeader(header)),
],
};
Expand All @@ -197,12 +248,12 @@ export class UtuProvider {

// Serialize each field
const serialized = [
"0x" + toLittleEndianHex(blockHeader.version),
formatFelt(toLittleEndianHex(blockHeader.version)),
...serializedHash(blockHeader.previousblockhash as string),
...serializedHash(blockHeader.merkleroot),
"0x" + toLittleEndianHex(blockHeader.time),
"0x" + blockHeader.bits,
"0x" + toLittleEndianHex(blockHeader.nonce),
formatFelt(toLittleEndianHex(blockHeader.time)),
formatFelt(blockHeader.bits),
formatFelt(toLittleEndianHex(blockHeader.nonce)),
];

return serialized;
Expand Down
153 changes: 152 additions & 1 deletion src/tests/UtuProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,157 @@ describe("UtuProvider", () => {
true
);

// console.log(updateCanonicalChainTx.calldata.join(", "));
expect(updateCanonicalChainTx.calldata).toEqual([
"0xd35a2",
"0xd35a3",
"0x105b1b4c",
"0x7abd4abf",
"0xf35e4b8a",
"0x4ee0c662",
"0x8a70cc8c",
"0xa7e70000",
"0x00000000",
"0x00000000",
"0x0",
"0x0040b422",
"0x04497c31",
"0x921daa0d",
"0xce160828",
"0x88d96ae0",
"0x6d4c21b5",
"0xe8350100",
"0x00000000",
"0x00000000",
"0x8747156c",
"0xaa39781d",
"0x2cf0292c",
"0x5ba0243e",
"0xfbd7f86e",
"0x4db390a3",
"0xddf94e99",
"0xee949321",
"0x90fa0d67",
"0x17030ecd",
"0x2a2312e7",
"0xb",
"0x01000000010000000000000000000000000000000000000000000000000000",
"0x000000000000ffffffff5603a2350d194d696e656420627920416e74506f6f",
"0x6c20e2002a00b4747806fabe6d6d710d04d1ea50a50e6329e2fa1ab865fa16",
"0x083c12ae90926ee2d687d78e64243210000000000000000000e27011020000",
"0x00000000ffffffff05220200000000000017a91442402a28dd61f2718a4b27",
"0xae72a4791d5bbdade787aca64c130000000017a9145249bdf2c131d43995cf",
"0xf42e8feee293f79297a8870000000000000000266a24aa21a9ed70918c3504",
"0x1817b2ce38010673f3420b25a34c0480a9e53a280f7eb1b0ccffdc00000000",
"0x000000002f6a2d434f52450164db24a662e20bbdf72d1cc6e973dbb2d12897",
"0xd54e3ecda72cb7961caa4b541b1e322bcfe0b5a03000000000000000002b6a",
"0x2952534b424c4f434b3a900671964dfd53207639c814270d32fbb670620e4d",
"0xdd8821dd3d5c100067a1e300000000",
"0xf",
"0xd",
"0xed1a7f4d",
"0xd014d433",
"0x61135d68",
"0xcd87ac3e",
"0x3fcdb176",
"0x7207eada",
"0x5841b71d",
"0x9d3b521a",
"0xb7385728",
"0x88aa8fd0",
"0x32ecc479",
"0x85bf025d",
"0x5845b20e",
"0xf7f2a5c9",
"0xa18769ed",
"0xfcb4b0f3",
"0xda98451b",
"0xd164c25a",
"0x5f344066",
"0x4b2d928f",
"0x8e8a5777",
"0x1b9c6920",
"0xd16fea50",
"0x79f038ea",
"0x68a9bb70",
"0x22840ac7",
"0x242401e0",
"0x5b163eec",
"0xd491a746",
"0x76169352",
"0x8d98d2bd",
"0x4e668543",
"0xabd0b481",
"0x25f96765",
"0x1c488cb2",
"0x708d2af5",
"0xd94c47fe",
"0x1c7dea31",
"0x3a7222a9",
"0xbdb319fa",
"0x19ef0283",
"0xb73d90ad",
"0x831fa829",
"0x264f5b5f",
"0x3c6b640a",
"0x2be01324",
"0x6672dede",
"0x1cf4f247",
"0x8d593a8f",
"0xae0ca5ae",
"0xfe2b942e",
"0xadd272e9",
"0xc6b72929",
"0xe2175560",
"0xed64e289",
"0xa644c603",
"0xf4e08ea5",
"0x157937e2",
"0xf748b7e3",
"0xca5b4631",
"0xd88087ba",
"0xb2c6ce01",
"0x7b488c35",
"0x4bfe4150",
"0x366d3c54",
"0xd4cc1cdc",
"0x1cfcbfdc",
"0x2dfa1047",
"0x566474be",
"0xb8af3799",
"0xc64a4d0a",
"0x737fa267",
"0x6df45507",
"0x69bdfaa3",
"0x7fdfa16c",
"0x42a3fccf",
"0xf2a3c4c1",
"0x5afc3719",
"0xb9255f4c",
"0xc9d70276",
"0xf42ae906",
"0xc504e17d",
"0x50d3e3e1",
"0x321b34b7",
"0x5a409ff8",
"0x61506203",
"0x9f9e556e",
"0xeaf6c329",
"0xa2b2c4ad",
"0x0b65a0cd",
"0x9f71a7aa",
"0x5bf78839",
"0x07059466",
"0x1cb48c27",
"0x4b9add9f",
"0x3ec6d0d9",
"0xf01e0809",
"0xf7f82ff9",
"0x96093cf9",
"0xab2671f3",
"0x8d65f3f7",
"0x5a13bf8d",
"0x976f697f",
"0xce132d37",
]);
});
});

0 comments on commit 9962fcf

Please sign in to comment.