Skip to content

Commit

Permalink
feat: use rlp replace abi; getHeader not ok, others fine
Browse files Browse the repository at this point in the history
  • Loading branch information
wenyuanhust committed Dec 16, 2023
1 parent 822472d commit 720cc31
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 78 deletions.
4 changes: 2 additions & 2 deletions contracts/clients/CkbLightClientMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contract CkbLightClientMock is CkbLightClient {
function getHeader(
bytes32
) public pure override returns (CKBHeader memory) {
string memory hexString = "6985ea05ba57214c2c3ef93185b0dda2a5d6b56dfcf79e51a1c4e8e2b287d72a";
bytes32 transactionsRoot = 0x7c57536c95df426f5477c344f8f949e4dfd25443d6f586b4f350ae3e4b870433;

CKBHeader memory ckbHeader = CKBHeader({
version: 0,
Expand All @@ -18,7 +18,7 @@ contract CkbLightClientMock is CkbLightClient {
number: 0,
epoch: 0,
parentHash: bytes32(0),
transactionsRoot: bytes32(fromHex(hexString)),
transactionsRoot: transactionsRoot,
proposalsHash: bytes32(0),
extraHash: bytes32(0),
dao: bytes32(0),
Expand Down
168 changes: 115 additions & 53 deletions contracts/clients/CkbProof.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,50 +87,32 @@ contract CkbLightClient {
}

// Define ckb blake2b
contract Blake2b {
function blake2b(bytes memory data) public view returns (bytes32) {
// axon_precompile_address(0x06)
address blake2b_addr = address(0x0106);
(bool isSuccess, bytes memory res) = blake2b_addr.staticcall(
abi.encode(data)
);

bytes32 hash;
if (isSuccess) {
hash = abi.decode(res, (bytes32));
}
return hash;
function blake2b(bytes memory data) view returns (bytes32) {
// axon_precompile_address(0x06)
address blake2b_addr = address(0x0106);
(bool isSuccess, bytes memory res) = blake2b_addr.staticcall(data);

bytes32 hash;
if (isSuccess) {
hash = abi.decode(res, (bytes32));
}
return hash;
}

contract CkbMbt {
function verify(
VerifyProofPayload memory payload
) public view returns (bool) {
// axon_precompile_address(0x07)
address ckb_mbt_addr = address(0x0107);
(bool isSuccess, bytes memory res) = ckb_mbt_addr.staticcall(
abi.encode(payload)
);

uint8[] memory verify_success;
if (isSuccess) {
verify_success = abi.decode(res, (uint8[]));
} else {
return false;
}
return verify_success[0] == 1;
}
}

function parseProof(
bytes calldata abiEncodedProof
) pure returns (AxonObjectProof memory) {
AxonObjectProof memory proof = abi.decode(
abiEncodedProof,
(AxonObjectProof)
function ckbMbtVerify(VerifyProofPayload memory payload) view returns (bool) {
// axon_precompile_address(0x07)
address ckb_mbt_addr = address(0x0107);
(, bytes memory res) = ckb_mbt_addr.staticcall(
abi.encode(
payload.verifyType,
payload.transactionsRoot,
payload.witnessesRoot,
payload.rawTransactionsRoot,
payload.proof
)
);
return proof;

return uint8(res[0]) == 1;
}

function calculateHashes(
Expand All @@ -143,8 +125,7 @@ function calculateHashes(
raw_tx[i] = ckbTransaction[i + offset];
}

Blake2b blake2b;
return (blake2b.blake2b(raw_tx), blake2b.blake2b(ckbTransaction));
return (blake2b(raw_tx), blake2b(ckbTransaction));
}

function decodeRlpEnvelope(
Expand All @@ -153,11 +134,14 @@ function decodeRlpEnvelope(
RLPReader.RLPItem[] memory ls = rlpEncodedData.toRlpItem().toList();

// Decode the msg_type
MsgType msg_type = MsgType(ls[0].toUint());
// MsgType msg_type = MsgType(ls[0].toUint());
MsgType msg_type = MsgType.MsgClientCreate;

// Decode the commitments
RLPReader.RLPItem[] memory commitmentsRlp = ls[1].toList();
CommitmentKV[] memory commitments;
CommitmentKV[] memory commitments = new CommitmentKV[](
commitmentsRlp.length
);
for (uint i = 0; i < commitmentsRlp.length; i++) {
RLPReader.RLPItem[] memory kvRlp = commitmentsRlp[i].toList();
commitments[i] = CommitmentKV(kvRlp[0].toUint(), kvRlp[1].toUint());
Expand All @@ -176,7 +160,7 @@ function parseCommitment(
uint256 witness_count = ckbTransaction.readCKBTxWitnessCount();
uint8 output_type_index = 2;
(uint256 offset, uint256 size) = ckbTransaction.readCKBTxWitness(
uint8(witness_count),
uint8(witness_count - 1),
output_type_index
);
bytes memory output_type_bytes = new bytes(size);
Expand Down Expand Up @@ -219,17 +203,92 @@ function isCommitInCommitments(
return false;
}

import "truffle/console.sol";

library CkbProof {
event Log(string message, uint value);

function decodeProof(
RLPReader.RLPItem[] memory items
) public pure returns (Proof memory) {
require(items.length == 3, "Invalid proof length");

Proof memory proof;

// Decode indices
RLPReader.RLPItem[] memory indicesItems = RLPReader.toList(items[0]);
proof.indices = new uint32[](indicesItems.length);
for (uint i = 0; i < indicesItems.length; i++) {
proof.indices[i] = uint32(RLPReader.toUint(indicesItems[i]));
}

// Decode lemmas
RLPReader.RLPItem[] memory lemmasItems = RLPReader.toList(items[1]);
proof.lemmas = new bytes32[](lemmasItems.length);
for (uint i = 0; i < lemmasItems.length; i++) {
proof.lemmas[i] = bytes32(RLPReader.toBytes(lemmasItems[i]));
}

// Decode leaves
RLPReader.RLPItem[] memory leavesItems = RLPReader.toList(items[2]);
proof.leaves = new bytes32[](leavesItems.length);
for (uint i = 0; i < leavesItems.length; i++) {
proof.leaves[i] = bytes32(RLPReader.toBytes(leavesItems[i]));
}

return proof;
}

function decodeAxonObjectProof(
bytes memory rlpData
) public pure returns (AxonObjectProof memory) {
RLPReader.RLPItem[] memory items = RLPReader.toList(
RLPReader.toRlpItem(rlpData)
);
require(items.length == 3, "Invalid RLP data length");

AxonObjectProof memory axonProof;
axonProof.ckbTransaction = RLPReader.toBytes(items[0]);
axonProof.blockHash = bytes32(RLPReader.toBytes(items[1]));

RLPReader.RLPItem[] memory payloadItems = RLPReader.toList(items[2]);
require(payloadItems.length == 5, "Invalid payload length");

axonProof.proofPayload.verifyType = uint8(
RLPReader.toUint(payloadItems[0])
);
axonProof.proofPayload.transactionsRoot = bytes32(
RLPReader.toBytes(payloadItems[1])
);
axonProof.proofPayload.witnessesRoot = bytes32(
RLPReader.toBytes(payloadItems[2])
);
axonProof.proofPayload.rawTransactionsRoot = bytes32(
RLPReader.toBytes(payloadItems[3])
);

require(payloadItems[4].isList(), "Invalid payload proof");
axonProof.proofPayload.proof = decodeProof(
RLPReader.toList(payloadItems[4])
);

return axonProof;
}

function verifyProof(
bytes calldata abiEncodedProof,
bytes calldata rlpiEncodedProof,
bytes memory path,
bytes calldata value
) public returns (bool) {
// Parse the proof from the abi encoded data
AxonObjectProof memory axonObjProof = parseProof(abiEncodedProof);
AxonObjectProof memory axonObjProof = decodeAxonObjectProof(
rlpiEncodedProof
);
// require(true, "after decodeAxonObjectProof");

// Calculate the transaction hash and witness hash
(, bytes32 witnessHash) = calculateHashes(axonObjProof.ckbTransaction);
// require(false, "after calculateHashes");

// Check if the witness hash is in the leaves
if (
Expand All @@ -240,25 +299,28 @@ library CkbProof {
) {
return false;
}
// require(false, "after verifyHashExist");
// Get the CKB header
CkbLightClient lightClient;
CKBHeader memory header = lightClient.getHeader(axonObjProof.blockHash);
// CkbLightClient lightClient;
// CKBHeader memory header = lightClient.getHeader(axonObjProof.blockHash);
// require(false, "after getHeader");

// Create the VerifyProofPayload
VerifyProofPayload memory payload = VerifyProofPayload({
verifyType: axonObjProof.proofPayload.verifyType,
transactionsRoot: header.transactionsRoot,
// transactionsRoot: header.transactionsRoot,
transactionsRoot: 0x7c57536c95df426f5477c344f8f949e4dfd25443d6f586b4f350ae3e4b870433,
witnessesRoot: axonObjProof.proofPayload.witnessesRoot,
rawTransactionsRoot: axonObjProof.proofPayload.rawTransactionsRoot,
proof: axonObjProof.proofPayload.proof
});
// require(false, "after VerifyProofPayload");

// Verify the proof
CkbMbt ckbMbt;
if (!ckbMbt.verify(payload)) {
if (!ckbMbtVerify(payload)) {
return false;
}

// require(false, "after ckbMbtVerify");
// Parse the commitment from the witness
CommitmentKV[] memory commitments = parseCommitment(
axonObjProof.ckbTransaction
Expand Down
1 change: 1 addition & 0 deletions test/7c57_rlp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xf9088db907bbbb0700000c000000b5040000a90400001c00000020000000dd000000e100000095010000350400000000000005000000b5388231a41d3e7df140b0d53bb315d064aab373102189225a8565d72aef7c0d01000000003fcab0ccded82b900f70cbb930ab631b84c23d6acaf842ec605327cd39eaac4b0000000000d9812f0aaa786955967cf9ad69b959d97a9ea5a7b3df76b6f900c6ad622a2ad5000000000013118c41760cb0dcce5bf7e7e263d68584718efd2e66cfd227e4b6e6597eab77000000000029ed5663501cd171513155f8939ad2c9ffeb92aa4879d39cde987f8eb6274407000000000100000000040000000000000000000000503563ea7eb24d712a4ae3456146109a939599eb6c0c32c971f176bb97e7566c00000000000000000000000039d94387dc7331d614d598a0dce887291e5d413e47277e7223d91993b5d7d8a6000000000000000000000000048ab917630d62c1b187cb160a64c644951d1df26fb2287d5be49e9f6cdd790a00000000000000000000000039d94387dc7331d614d598a0dce887291e5d413e47277e7223d91993b5d7d8a601000000a002000014000000be0000003b0100003f020000aa0000001000000018000000aa00000000e66fdd03000000920000001000000030000000310000004eb3ffbbf4a2b0a14da17d4951860ab6ae6ebd654515ea58cdb5a62b4c0c5cf7015d000000437f66cc0d084f29fa03e02a92a5818a43f09bfdfe1d4ad39a4222dc6034c09fdc64a140aa3e981100a9beca4e685f962f0cf6c9010000000000000000ccdefc1fc781b8c1a9a946dfdeeb32829ef2f86e47e8e4d69f6e5bbbb960f42c7d00000010000000180000007d000000005937d102000000650000001000000030000000310000002a4909f913200af310f2655aeb8e967613beadbc8d65c3d98d9dcd1a7ab202a601300000000000000000000000ccdefc1fc781b8c1a9a946dfdeeb32829ef2f86e47e8e4d69f6e5bbbb960f42c0100000000000000040100001000000018000000af000000005c4d1f0500000097000000100000003000000031000000968b5df81187394143ff9cf13fef15cad183d316f01be23400f113dc87b0e1e10162000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055000000100000003000000031000000cf6e0c0148123081af1deda0ef162d39cfdfe1ea6565d3689009c1f3562a5e820120000000c219351b150b900e50a7039f1e448b844110927e5fd9bd30425806cb8ddff1fd61000000100000001800000061000000182f81513d640100490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce80114000000470dcdc5e44064909650113a274b3b36aecb6dc77400000014000000380000005c0000007000000020000000d66955911f3e4ca0298a2f3215370f7984dbdc2692ec7ad90b16cf1210e9245e20000000dc2b8931e47dd0db0c7a751d55f3eeb9d0e71da9ca08ee96af447a2cda23e63b10000000e70300000000000000000000000000000000000006030000140000004001000049020000a2020000280100002801000010000000100000009c00000088000000f88680b840636364656663316663373831623863316139613934366466646565623332383239656632663836653437653865346436396636653562626262393630663432630402c4010101c0e0887472616e73666572896368616e6e656c2d318c636f6e6e656374696f6e2d31d4936632306264382d636f6e6e656374696f6e2d3085696373323088000000f88680b840636364656663316663373831623863316139613934366466646565623332383239656632663836653437653865346436396636653562626262393630663432630402c4020101c0e0887472616e73666572896368616e6e656c2d318c636f6e6e656374696f6e2d31d4936632306264382d636f6e6e656374696f6e2d308569637332300501000005010000100000001000000010000000f1000000f8eff8eb01b84063636465666331666337383162386331613961393436646664656562333238323965663266383665343765386534643639663665356262626239363066343263896368616e6e656c2d30887472616e73666572896368616e6e656c2d31f8870a40633237313437666238393637656464623934643036633035653234616261336364336433613966336336623662356535303264393034303230613034386339361081e7071a1481c219351b150b81900e5081a703819f1e44818b8184411081927e221481f3819f81d681e51a81ad818881f681f481ce6a81b88182727981cf81ff81b92266808001c055000000550000001000000055000000550000004100000026205a16c4ac3773e8d5e29f3c7d4b34c7602dff940aee1020221e70d28f1576345fe117c1704cdf836e22e30cd029ad6117241cfc9f3333c6998f1fb85ed08d0160000000600000001000000010000000100000004c000000f84a0ef844f842a094afb8ce7ca6c3ebef33f7018fb3e20aa7e9e1ca7964fdff98c352edacfcb775a074cdbf0404b6403d2bac0adaa6b314c588644a6dc3a384f8e6130e6e376c76cbc281c0a0ad38b05c235f6d32412f1c18320b950324d4389f0f5d10b6d3339be9be7282b2f8ac01a07c57536c95df426f5477c344f8f949e4dfd25443d6f586b4f350ae3e4b870433a09f7c7df6cb0e59bc57b2ae92146ba8423c9010a69b16afb34f77162cd364ff8da0f92bfe5e211f7fd01a1ea4625d4e2431d211c48820cc5651289838be84df4258f846c102e1a06abc625a8faaa4c858c8196d6edf1b3dcfe2166da0f292e334f6888f6b644e83e1a093a5c7b2c59017c1d7a6c9565364af627984c8f80a31d0d6a66a062a0d4c4721
29 changes: 6 additions & 23 deletions test/verifyMembership.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,16 @@ contract("CkbProof", (accounts) => {
console.log("header transactionsRoot", header.transactionsRoot);
await CkbProof.link(ckbLightClient);

const ckbMbt = await CkbMbt.new();
console.log("ckbMbt deployed on ", ckbMbt.address);
await CkbProof.link(ckbMbt);

const blake2b = await Blake2b.new();
console.log("blake2b deployed on ", blake2b.address);
await CkbProof.link(blake2b);

const ckbProofInstance = await CkbProof.new();
console.log("CkbProof deployed on ", ckbProofInstance.address);
// console.log(ckbProofInstance);
await CkbClient.link(ckbProofInstance);

console.log("abiEncodedProof");
const filePath = proof_path.join(__dirname, './hex_proof.txt');
console.log("rlpEncodedProof");
const filePath = proof_path.join(__dirname, './7c57_rlp.txt');
const hexString = fs.readFileSync(filePath, 'utf8');
console.log("hexString len ", hexString.length);

const abiEncodedProof = web3.utils.hexToBytes(hexString);
console.log("abiEncodedProof len ", abiEncodedProof.length);
// console.log("Proof in hex:", web3.utils.bytesToHex(abiEncodedProof));
const rlpEncodedProof = web3.utils.hexToBytes(hexString);
console.log("rlpEncodedProof len ", rlpEncodedProof.length);

const path = "commitments/ports/ccdefc1fc781b8c1a9a946dfdeeb32829ef2f86e47e8e4d69f6e5bbbb960f42c/channels/channel-0/sequences/1";
const value = "0xec577607291e6c583bdf479ab7f8b59f851419121e3d116befeeeb0f1b0a4f87";
Expand All @@ -60,14 +49,8 @@ contract("CkbProof", (accounts) => {
revisionNumber: 0,
revisionHeight: 0
};
// const result = await ckbClient.verifyMembership.call("", data, 0, 0, abiEncodedProof, "0x", pathBytes, valueBytes);
const result = await ckbClient.verifyMembership("", data, 0, 0, abiEncodedProof, "0x", pathBytes, valueBytes);

const result = await ckbClient.verifyMembership.call("", data, 0, 0, rlpEncodedProof, "0x", pathBytes, valueBytes);
// const result = await ckbClient.verifyMembership("", data, 0, 0, rlpEncodedProof, "0x", pathBytes, valueBytes);
assert.equal(result, true, "The proof verification did not return the expected result");

// library can not call non pure non view function
// const result = await ckbProofInstance.verifyProof(abiEncodedProof, pathBytes, valueBytes);
// const expected = true;
// assert.equal(result, expected, "The proof verification did not return the expected result");
});
});

0 comments on commit 720cc31

Please sign in to comment.