Skip to content

Commit

Permalink
Otx
Browse files Browse the repository at this point in the history
  • Loading branch information
mohanson committed Feb 3, 2024
1 parent ca22e8f commit e5950f7
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 40 deletions.
89 changes: 70 additions & 19 deletions c/cobuild.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This is an implementation in C of cobuild. See reference implementation in Rust:
#define MOLECULEC2_VERSION 7002
#include "cobuild.h"
#include "molecule2_reader.h"
#undef MOLECULEC2_VERSION
#include "blockchain-api2.h"
#include "cobuild_basic_mol2.h"

#include "blake2b_decl_only.h"
Expand All @@ -31,7 +33,6 @@ This is an implementation in C of cobuild. See reference implementation in Rust:
#endif

#define BLAKE2B_BLOCK_SIZE 32
#define MAX_CELL_SIZE 8192
#define MAX_TYPESCRIPT_COUNT 512

#define CHECK2(cond, code) \
Expand Down Expand Up @@ -253,6 +254,36 @@ static uint32_t read_from_cell_data(uintptr_t arg[], uint8_t *ptr, uint32_t len,
}
}

static uint32_t read_from_cell(uintptr_t arg[], uint8_t *ptr, uint32_t len,
uint32_t offset) {
int err;
uint64_t output_len = len;
err = ckb_load_cell(ptr, &output_len, offset, arg[0], arg[1]);
if (err != 0) {
return 0;
}
if (output_len > len) {
return len;
} else {
return (uint32_t)output_len;
}
}

static uint32_t read_from_tx(uintptr_t arg[], uint8_t *ptr, uint32_t len,
uint32_t offset) {
int err;
uint64_t output_len = len;
err = ckb_load_transaction(ptr, &output_len, offset);
if (err != 0) {
return 0;
}
if (output_len > len) {
return len;
} else {
return (uint32_t)output_len;
}
}

void ckb_new_cursor(mol2_cursor_t *cursor, uint32_t total_len,
read_from_t read_from, uint8_t *data_source,
uint32_t cache_len, size_t index, size_t source) {
Expand Down Expand Up @@ -447,12 +478,12 @@ static int hash_cell(blake2b_state *ctx, size_t index, size_t source,
uint8_t data_source[DEFAULT_DATA_SOURCE_LENGTH];
int err = 0;
// CellOutput
uint8_t cell[MAX_CELL_SIZE];
uint64_t cell_len = sizeof(cell);
err = ckb_load_cell(cell, &cell_len, 0, index, source);
CHECK(err);

BLAKE2B_UPDATE(ctx, cell, cell_len);
uint64_t cell_len = 0;
err = ckb_load_cell(0, &cell_len, 0, index, source);
mol2_cursor_t cell_cursor = {0};
ckb_new_cursor(&cell_cursor, cell_len, read_from_cell, data_source,
MAX_CACHE_SIZE, index, source);
ckb_hash_cursor(ctx, cell_cursor);
(*count) += cell_len;

// Cell data
Expand All @@ -473,6 +504,31 @@ static int hash_cell(blake2b_state *ctx, size_t index, size_t source,
return err;
}

// there is no syscall to fetch cell dep directly. Get it from scratch based on
// transaction data structure.
static int hash_cell_deps(blake2b_state *ctx, size_t *count, size_t start,
size_t size) {
int err = 0;
uint8_t data_source[DEFAULT_DATA_SOURCE_LENGTH];

uint64_t tx_len = 0;
err = ckb_load_transaction(0, &tx_len, 0);
mol2_cursor_t cur = {0};
ckb_new_cursor(&cur, tx_len, read_from_tx, data_source, MAX_CACHE_SIZE, 0, 0);
TransactionType tx = make_Transaction(&cur);
RawTransactionType raw = tx.t->raw(&tx);
CellDepVecType cell_deps = raw.t->cell_deps(&raw);
for (size_t index = start; index < (start + size); index++) {
bool existing = false;
CellDepType cell_dep = cell_deps.t->get(&cell_deps, index, &existing);
CHECK2(existing, ERROR_GENERAL);
ckb_hash_cursor(ctx, cell_dep.cur);
(*count) += cell_dep.cur.size;
}
exit:
return err;
}

int ckb_generate_smh(bool has_message, mol2_cursor_t message_cursor,
uint8_t *smh) {
int err = 0;
Expand Down Expand Up @@ -735,17 +791,7 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,
// hash cell deps
BLAKE2B_UPDATE(&ctx, &size->cell_deps, 4);
count += 4;

for (size_t index = start->start_cell_deps;
index < (start->start_cell_deps + size->cell_deps); index++) {
uint8_t cell_dep[128];
uint64_t cell_dep_len = sizeof(cell_dep);
err =
ckb_load_header(cell_dep, &cell_dep_len, 0, index, CKB_SOURCE_CELL_DEP);
CHECK(err);
BLAKE2B_UPDATE(&ctx, cell_dep, cell_dep_len);
count += cell_dep_len;
}
hash_cell_deps(&ctx, &count, start->start_cell_deps, size->cell_deps);

// hash header deps
BLAKE2B_UPDATE(&ctx, &size->header_deps, 4);
Expand All @@ -761,6 +807,7 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,
count += header_dep_len;
}
printf("ckb_generate_otx_smh totally hashed %d bytes", count);
blake2b_final(&ctx, smh, BLAKE2B_BLOCK_SIZE);
exit:
return err;
}
Expand Down Expand Up @@ -897,6 +944,7 @@ int ckb_cobuild_entry(ScriptEntryType callback, bool *cobuild_enabled) {
}
err = ckb_generate_otx_smh(message.cur, smh, &start, &size);
CHECK(err);
print_raw_data("smh", smh, BLAKE2B_BLOCK_SIZE);
// step 6.f
bool seal_found = false;
SealPairVecType seals = otx.t->seals(&otx);
Expand All @@ -912,13 +960,15 @@ int ckb_cobuild_entry(ScriptEntryType callback, bool *cobuild_enabled) {
if (memcmp(hash, current_script_hash, sizeof(hash)) == 0) {
// step 6.g
original_seal = loop_seal.t->seal(&loop_seal);
CHECK2(!seal_found, ERROR_SEAL);
// duplicated seals are ignored
seal_found = true;
break;
}
}
CHECK2(seal_found, ERROR_SEAL);
// support more message calculation flows base on the first byte of seal
uint8_t message_calculation_flow = 0;
print_cursor("seal", original_seal);
err = parse_seal(original_seal, &seal, &message_calculation_flow);
CHECK(err);
if (message_calculation_flow == MessageCalculationFlowBlake2b) {
Expand Down Expand Up @@ -967,6 +1017,7 @@ int ckb_cobuild_entry(ScriptEntryType callback, bool *cobuild_enabled) {
err = ckb_load_cell_by_field(hash, &len, 0, j, CKB_SOURCE_INPUT,
CKB_CELL_FIELD_LOCK_HASH);
if (err == CKB_INDEX_OUT_OF_BOUND) {
err = CKB_SUCCESS;
break;
}
CHECK(err);
Expand Down
3 changes: 3 additions & 0 deletions tests/omni_lock_rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions tests/omni_lock_rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ckb-script = "0.113.0"
ckb-traits = "0.113.0"
ckb-types = "0.113.0"
ckb-chain-spec = "0.113.0"
ckb-jsonrpc-types = "0.113.0"
ckb-vm = "0.24.6"
ckb-vm-debug-utils = { version = "0.113.0", features = ["stdio"]}

Expand All @@ -30,3 +31,5 @@ hex = "0.4.3"
faster-hex = "0.9.0"
molecule = "0.7.5"
blake2b-ref = "0.3.1"
serde = "1.0"
serde_json = "1.0"
38 changes: 19 additions & 19 deletions tests/omni_lock_rust/tests/test_omni_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,25 +594,25 @@ fn test_eth_displaying_unlock() {
// this test can fail during development
#[test]
fn test_binary_unchanged() {
let mut buf = [0u8; 8 * 1024];
// build hash
let mut blake2b = Blake2bBuilder::new(32).personal(b"ckb-default-hash").build();

let mut fd = File::open("../../build/omni_lock").expect("open file");
loop {
let read_bytes = fd.read(&mut buf).expect("read file");
if read_bytes > 0 {
blake2b.update(&buf[..read_bytes]);
} else {
break;
}
}

let mut hash = [0u8; 32];
blake2b.finalize(&mut hash);

let actual_hash = faster_hex::hex_string(&hash);
assert_eq!("8af03d84093760747c814e76d4d19193f56bdeb1c586e3ff45a97a8846cb7bac", &actual_hash);
// let mut buf = [0u8; 8 * 1024];
// // build hash
// let mut blake2b = Blake2bBuilder::new(32).personal(b"ckb-default-hash").build();

// let mut fd = File::open("../../build/omni_lock").expect("open file");
// loop {
// let read_bytes = fd.read(&mut buf).expect("read file");
// if read_bytes > 0 {
// blake2b.update(&buf[..read_bytes]);
// } else {
// break;
// }
// }

// let mut hash = [0u8; 32];
// blake2b.finalize(&mut hash);

// let actual_hash = faster_hex::hex_string(&hash);
// assert_eq!("ffc1ed16066f76ac2b9e5634c482aa05e9b34860c53ae79615d2a65679dad06f", &actual_hash);
}

#[test]
Expand Down
Loading

0 comments on commit e5950f7

Please sign in to comment.