Skip to content

Commit

Permalink
Extra steps for otx
Browse files Browse the repository at this point in the history
  • Loading branch information
XuJiandong committed Jan 31, 2024
1 parent b8a68fc commit befe5e8
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 27 deletions.
101 changes: 83 additions & 18 deletions c/cobuild.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This is an implementation in C of cobuild. See reference implementation in Rust:

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

#define CHECK2(cond, code) \
do { \
Expand Down Expand Up @@ -66,6 +67,7 @@ enum CobuildErrorCode {
ERROR_SEAL,
ERROR_FLOW,
ERROR_OTX_START_DUP,
ERROR_WRONG_OTX,
};

enum WitnessLayoutId {
Expand Down Expand Up @@ -97,7 +99,8 @@ const char *PERSONAL_SIGHASH_ALL = "ckb-tcob-sighash";
const char *PERSONAL_SIGHASH_ALL_ONLY = "ckb-tcob-sgohash";
const char *PERSONAL_OTX = "ckb-tcob-otxhash";

#define MAX_TYPESCRIPT_COUNT 512
// forward declaration
int ckb_calculate_inputs_len();

/*
The seal cursor uses this data source. So the lifetime of data source should
Expand Down Expand Up @@ -138,8 +141,8 @@ void print_cursor(const char *name, mol2_cursor_t cursor) {
}

// After being enabled, there will be a lot of logs.
#define BLAKE2B_UPDATE blake2b_update_debug
// #define BLAKE2B_UPDATE blake2b_update
// #define BLAKE2B_UPDATE blake2b_update_debug
#define BLAKE2B_UPDATE blake2b_update
int blake2b_update_debug(blake2b_state *S, const void *pin, size_t inlen) {
blake2b_update(S, pin, inlen);
print_raw_data("blake2b_update: ", (uint8_t *)pin, inlen);
Expand Down Expand Up @@ -504,8 +507,8 @@ static int hash_cell(blake2b_state *ctx, size_t index, size_t source,
BLAKE2B_UPDATE(ctx, &cell_data_len, 4);
(*count) += 4;
err = ckb_hash_cursor(ctx, cell_data_cursor);
(*count) += cell_data_cursor.size;
CHECK(err);
(*count) += cell_data_cursor.size;

exit:
return err;
Expand Down Expand Up @@ -733,10 +736,11 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,

err = ckb_hash_cursor(&ctx, message_cursor);
CHECK(err);
count += message_cursor.size;

BLAKE2B_UPDATE(&ctx, &size->input_cells, 4);
count += 4;

uint32_t inputs_len = size->input_cells;
BLAKE2B_UPDATE(&ctx, &inputs_len, sizeof(inputs_len));
count += sizeof(inputs_len);
// hash input cell and data
for (size_t index = start->start_input_cell;
index < (start->start_input_cell + size->input_cells); index++) {
Expand All @@ -752,19 +756,17 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,
CHECK(err);
}
// hash output cell and data
uint32_t outputs_len = size->output_cells;
BLAKE2B_UPDATE(&ctx, &outputs_len, sizeof(outputs_len));
count += sizeof(outputs_len);
BLAKE2B_UPDATE(&ctx, &size->output_cells, 4);
count += 4;
for (size_t index = start->start_output_cell;
index < (start->start_output_cell + size->output_cells); index++) {
err = hash_cell(&ctx, index, CKB_SOURCE_OUTPUT, &count);
CHECK(err);
}

// hash cell deps
uint32_t celldeps_len = size->cell_deps;
BLAKE2B_UPDATE(&ctx, &celldeps_len, sizeof(celldeps_len));
count += sizeof(celldeps_len);
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++) {
Expand All @@ -778,9 +780,8 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,
}

// hash header deps
uint32_t headerdeps_len = size->header_deps;
BLAKE2B_UPDATE(&ctx, &headerdeps_len, sizeof(headerdeps_len));
count += sizeof(headerdeps_len);
BLAKE2B_UPDATE(&ctx, &size->header_deps, 4);
count += 4;
for (size_t index = start->start_header_deps;
index < (start->start_header_deps + size->header_deps); index++) {
uint8_t header_dep[32];
Expand All @@ -796,6 +797,25 @@ int ckb_generate_otx_smh(mol2_cursor_t message_cursor, uint8_t *smh,
return err;
}

static bool is_otx_witness(size_t index, bool *out_of_bounds) {
int err = 0;
uint32_t id = 0;
uint64_t id_len = sizeof(id);
*out_of_bounds = false;
err = ckb_load_witness(&id, &id_len, 0, index, CKB_SOURCE_INPUT);
if (err == CKB_INDEX_OUT_OF_BOUND) {
*out_of_bounds = true;
return false;
}
if (err) {
return false;
}
if (id_len < sizeof(id)) {
return false;
}
return id == WitnessLayoutOtx;
}

int ckb_cobuild_entry(ScriptEntryType callback) {
int err = 0;
uint8_t smh[BLAKE2B_BLOCK_SIZE];
Expand All @@ -813,6 +833,7 @@ int ckb_cobuild_entry(ScriptEntryType callback) {
bool has_otx = false;
OtxStart otx_start = {0};
// step 2
// step 4
err = ckb_fetch_otx_start(&has_otx, &i, &otx_start);
CHECK(err);
if (!has_otx) {
Expand All @@ -828,17 +849,20 @@ int ckb_cobuild_entry(ScriptEntryType callback) {
ce = cs;
hs = otx_start.start_header_deps;
he = hs;
for (size_t index = i + 1;; index++) {
size_t index = i + 1;
for (;; index++) {
mol2_cursor_t cursor;
err = ckb_new_witness_cursor(&cursor, g_cobuild_seal_data_source,
MAX_CACHE_SIZE, index, CKB_SOURCE_INPUT);
if (err == CKB_INDEX_OUT_OF_BOUND) {
// step 6, not WitnessLayoutOtx
break;
}
CHECK(err);
uint32_t id = 0;
err = try_union_unpack_id(&cursor, &id);
if (err) {
// step 6, not WitnessLayoutOtx
// maybe WitnessArgs or empty
break;
}
Expand Down Expand Up @@ -896,6 +920,7 @@ int ckb_cobuild_entry(ScriptEntryType callback) {
if (memcmp(hash, current_script_hash, sizeof(hash)) == 0) {
// step 6.f
seal = loop_seal.t->seal(&loop_seal);
CHECK2(!seal_found, ERROR_SEAL);
seal_found = true;
}
}
Expand All @@ -917,6 +942,46 @@ int ckb_cobuild_entry(ScriptEntryType callback) {
break;
}
} // end of step 6 loop

// step 7
size_t j = index;
// [0, i)
for (size_t index = 0; index < i; i++) {
bool out_of_bounds = false;
CHECK2(!is_otx_witness(index, &out_of_bounds), ERROR_WRONG_OTX);
}
// [j, +infinite]
for (size_t index = j;; index++) {
bool out_of_bounds = false;
CHECK2(!is_otx_witness(index, &out_of_bounds), ERROR_WRONG_OTX);
if (out_of_bounds) {
break;
}
}
// step 8
size_t inputs_len = ckb_calculate_inputs_len();
bool found = false;
for (size_t index = 0; index < inputs_len; index++) {
// scan all input cell in [0, is) and [ie, +infinity)
if (index < is || index >= ie) {
uint8_t hash[BLAKE2B_BLOCK_SIZE];
uint64_t len = BLAKE2B_BLOCK_SIZE;
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) {
break;
}
CHECK(err);
if (memcmp(hash, current_script_hash, sizeof(hash)) == 0) {
found = true;
break;
}
}
}
if (found) {
err = ckb_cobuild_normal_entry(callback);
CHECK(err);
}
exit:
return err;
}
}
16 changes: 8 additions & 8 deletions c/omni_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ typedef struct WitnessLockType {
SmtProofEntryVecType proofs;
} WitnessLockType;

uint8_t code_buff[MAX_CODE_SIZE] __attribute__((aligned(RISCV_PGSIZE)));
uint8_t g_code_buff[MAX_CODE_SIZE] __attribute__((aligned(RISCV_PGSIZE)));

// make compiler happy
int make_cursor_from_witness(WitnessArgsType *witness, bool *_input) {
Expand Down Expand Up @@ -315,14 +315,11 @@ int smt_verify_identity(CkbIdentityType *id, SmtProofEntryVecType *proofs,
}

static int parse_witness_lock(WitnessLockType *witness_lock,
mol2_cursor_t *seal, bool witness_existing) {
mol2_cursor_t *seal) {
int err = 0;
witness_lock->has_signature = false;
witness_lock->has_identity = false;
witness_lock->has_proofs = false;
if (!witness_existing) {
return 0;
}
// convert Bytes to OmniLockWitnessLock
OmniLockWitnessLockType mol_witness_lock = make_OmniLockWitnessLock(seal);
IdentityOptType identity_opt =
Expand Down Expand Up @@ -393,8 +390,11 @@ int omnilock_entry(const uint8_t *smh, mol2_cursor_t seal, bool cobuild_enabled,
// this identity can be either from witness lock (witness_lock.id) or script
// args (args.id)
CkbIdentityType identity = {0};
err = parse_witness_lock(&witness_lock, &seal, witness_existing);
CHECK(err);
// In some scenarios(e.g. owner lock), corresponding witness doesn't exist
if (witness_existing) {
err = parse_witness_lock(&witness_lock, &seal);
CHECK(err);
}

err = parse_args(&args);
CHECK(err);
Expand Down Expand Up @@ -445,7 +445,7 @@ int omnilock_entry(const uint8_t *smh, mol2_cursor_t seal, bool cobuild_enabled,
return check_payment_unlock(min_ckb_amount, min_udt_amount);
}
}
ckb_identity_init_code_buffer(code_buff, MAX_CODE_SIZE);
ckb_identity_init_code_buffer(g_code_buff, MAX_CODE_SIZE);
err = ckb_verify_identity(&identity, witness_lock.signature,
witness_lock.signature_size, witness_lock.preimage,
witness_lock.preimage_size, smh);
Expand Down
2 changes: 1 addition & 1 deletion tests/omni_lock_rust/tests/test_omni_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ fn test_binary_unchanged() {

let actual_hash = faster_hex::hex_string(&hash);
assert_eq!(
"187a5bfaad0aef3c9e7d71f840f7848b4dd88fc695377e09ce0b0aa5f5533738",
"de18c338ecb57ee4a5d2fe0d0983ab5a3d0ee4f8bd920e793ce0296c9fc3ac60",
&actual_hash
);
}
Expand Down

0 comments on commit befe5e8

Please sign in to comment.