diff --git a/Makefile b/Makefile index 1c46576..422db1b 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,15 @@ CC := $(TARGET)-gcc LD := $(TARGET)-gcc OBJCOPY := $(TARGET)-objcopy CFLAGS := -fPIC -O3 -fno-builtin-printf -fno-builtin-memcmp -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I deps/secp256k1/src -I deps/secp256k1 -I deps/ckb-c-std-lib -I deps/ckb-c-std-lib/libc -I deps/ckb-c-std-lib/molecule -I c -I build -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g -LDFLAGS := -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections +LDFLAGS := -nostdlib -nostartfiles -fno-builtin -Wl,-static -Wl,--gc-sections SECP256K1_SRC_20210801 := deps/secp256k1-20210801/src/ecmult_static_pre_context.h OMNI_LOCK_CFLAGS :=$(subst ckb-c-std-lib,ckb-c-stdlib-20210801,$(CFLAGS)) -I deps/sparse-merkle-tree/c OMNI_LOCK_CFLAGS := $(subst secp256k1,secp256k1-20210801,$(OMNI_LOCK_CFLAGS)) +# enable log +# OMNI_LOCK_CFLAGS += -DCKB_C_STDLIB_PRINTF -DCKB_C_STDLIB_PRINTF_BUFFER_SIZE=1024 + PROTOCOL_HEADER := c/blockchain.h PROTOCOL_SCHEMA := c/blockchain.mol @@ -54,7 +57,8 @@ ${PROTOCOL_SCHEMA}: curl -L -o $@ ${PROTOCOL_URL} ALL_C_SOURCE := $(wildcard c/omni_lock.c c/omni_lock_acp.h c/omni_lock_time_lock.h \ - tests/omni_lock/omni_lock_sim.c tests/omni_lock/ckb_syscall_omni_lock_sim.h tests/omni_lock/omni_lock_supply.h) + tests/omni_lock/omni_lock_sim.c tests/omni_lock/ckb_syscall_omni_lock_sim.h tests/omni_lock/omni_lock_supply.h\ + c/blake2b_decl_only.h c/cobuild.h c/cobuild.c) fmt: docker run --rm -v `pwd`:/code ${CLANG_FORMAT_DOCKER} bash -c "cd code && clang-format -i -style=Google $(ALL_C_SOURCE)" @@ -62,6 +66,7 @@ fmt: mol: make omni_lock_mol + make cobuild_mol c/xudt_rce_mol.h: c/xudt_rce.mol ${MOLC} --language c --schema-file $< > $@ @@ -76,17 +81,27 @@ omni_lock_mol: ${MOLC} --language - --schema-file c/omni_lock.mol --format json > build/omni_lock_mol2.json moleculec-c2 --input build/omni_lock_mol2.json | clang-format -style=Google > c/omni_lock_mol2.h -build/omni_lock: c/omni_lock.c c/omni_lock_supply.h c/omni_lock_acp.h c/secp256k1_lock.h build/secp256k1_data_info_20210801.h $(SECP256K1_SRC_20210801) c/ckb_identity.h - $(CC) $(OMNI_LOCK_CFLAGS) $(LDFLAGS) -o $@ $< +build/cobuild.o: c/cobuild.c c/cobuild.h + $(CC) -c $(OMNI_LOCK_CFLAGS) -o $@ $< + +build/omni_lock.o: c/omni_lock.c c/omni_lock_supply.h c/omni_lock_acp.h c/secp256k1_lock.h build/secp256k1_data_info_20210801.h $(SECP256K1_SRC_20210801) c/ckb_identity.h + $(CC) -c $(OMNI_LOCK_CFLAGS) -o $@ $< + +build/omni_lock: build/omni_lock.o build/cobuild.o + $(CC) $(LDFLAGS) -o $@ $^ cp $@ $@.debug $(OBJCOPY) --strip-debug --strip-all $@ +cobuild_mol: + ${MOLC} --language rust --schema-file c/basic.mol | rustfmt > tests/omni_lock_rust/src/schemas/basic.rs + ${MOLC} --language rust --schema-file c/top_level.mol | rustfmt > tests/omni_lock_rust/src/schemas/top_level.rs clean: rm -rf build/secp256k1_data_info_20210801.h build/dump_secp256k1_data_20210801 rm -rf build/secp256k1_data_20210801 rm -rf build/*.debug rm -f build/omni_lock + rm -f build/*.o cd deps/secp256k1-20210801 && [ -f "Makefile" ] && make clean install-tools: diff --git a/README.md b/README.md index 9c80f45..2bfae43 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,4 @@ cd tests/omni_lock_rust && cargo test ## Deployment See [RFC](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0042-omnilock/0042-omnilock.md) + diff --git a/c/basic.mol b/c/basic.mol new file mode 100644 index 0000000..59cc5b2 --- /dev/null +++ b/c/basic.mol @@ -0,0 +1,81 @@ +import blockchain; + +array Hash [byte; 32]; +vector String ; // UTF-8 encoded +option Uint32Opt (Uint32); + +table Action { + script_info_hash: Byte32, // script info + script_hash: Byte32, // script + data: Bytes, // action data +} + +vector ActionVec ; + +table Message { + actions: ActionVec, +} + +table ScriptInfo { + // The dapp name and domain the script belongs to + name: String, + url: String, + + // Script info. + // schema: script action schema + // message_type: the entry action type used in WitnessLayout + script_hash: Byte32, + schema: String, + message_type: String, +} + +vector ScriptInfoVec ; + +table ResolvedInputs { + outputs: CellOutputVec, + outputs_data: BytesVec, +} + +table BuildingPacketV1 { + message: Message, + payload: Transaction, + resolved_inputs: ResolvedInputs, + change_output: Uint32Opt, + script_infos: ScriptInfoVec, + lock_actions: ActionVec, +} + +union BuildingPacket { + BuildingPacketV1, +} + +table SighashAll { + message: Message, + seal: Bytes, +} + +table SighashAllOnly { + seal: Bytes, +} + +table SealPair { + script_hash: Byte32, + seal: Bytes, +} +vector SealPairVec ; + +table OtxStart { + start_input_cell: Uint32, + start_output_cell: Uint32, + start_cell_deps: Uint32, + start_header_deps: Uint32, +} + +table Otx { + input_cells: Uint32, + output_cells: Uint32, + cell_deps: Uint32, + header_deps: Uint32, + message: Message, + seals: SealPairVec, +} \ No newline at end of file diff --git a/c/blake2b_decl_only.h b/c/blake2b_decl_only.h new file mode 100644 index 0000000..eb069e3 --- /dev/null +++ b/c/blake2b_decl_only.h @@ -0,0 +1,61 @@ + +#ifndef __BLAKE2B_DECL_ONLY_H__ +#define __BLAKE2B_DECL_ONLY_H__ + +#include +#include + +#define BLAKE2_PACKED(x) x __attribute__((packed)) + +enum blake2b_constant { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 +}; +BLAKE2_PACKED(struct blake2b_param__ { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ +}); + +typedef struct blake2b_param__ blake2b_param; + +typedef struct blake2b_state__ { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; +} blake2b_state; + +/* Streaming API */ +int ckb_blake2b_init(blake2b_state *S, size_t outlen); +int blake2b_init(blake2b_state *S, size_t outlen); +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, + size_t keylen); +int blake2b_update(blake2b_state *S, const void *in, size_t inlen); +int blake2b_final(blake2b_state *S, void *out, size_t outlen); +/* Simple API */ +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen); + +/* This is simply an alias for blake2b */ +int blake2(void *out, size_t outlen, const void *in, size_t inlen, + const void *key, size_t keylen); + +int blake2b_init_param(blake2b_state *S, const blake2b_param *P); + +#endif diff --git a/c/ckb_identity.h b/c/ckb_identity.h index f006f8b..056285e 100644 --- a/c/ckb_identity.h +++ b/c/ckb_identity.h @@ -25,11 +25,7 @@ #define MAX_PREIMAGE_SIZE 1024 #define MESSAGE_HEX_LEN 64 -<<<<<<< HEAD const char BTC_PREFIX[] = "CKB (Bitcoin Layer) transaction: 0x"; -======= -const char BTC_PREFIX[] = "CKB (Bitcoin Layer-2) transaction: 0x"; ->>>>>>> bcd9b58 (Add missing auth id(0x02~0x05)) // BTC_PREFIX_LEN = 35 const size_t BTC_PREFIX_LEN = sizeof(BTC_PREFIX) - 1; @@ -87,6 +83,9 @@ typedef int (*validate_signature_t)(void *prefilled_data, const uint8_t *sig, typedef int (*convert_msg_t)(const uint8_t *msg, size_t msg_len, uint8_t *new_msg, size_t new_msg_len); +bool g_cobuild_enabled = false; +uint8_t g_cobuild_signing_message_hash[32]; + static void bin_to_hex(const uint8_t *source, uint8_t *dest, size_t len) { const static uint8_t HEX_TABLE[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; @@ -379,6 +378,11 @@ int validate_signature_eos(void *prefilled_data, const uint8_t *sig, } int generate_sighash_all(uint8_t *msg, size_t msg_len) { + if (g_cobuild_enabled) { + memcpy(msg, g_cobuild_signing_message_hash, BLAKE2B_BLOCK_SIZE); + return 0; + } + int ret; uint64_t len = 0; unsigned char temp[MAX_WITNESS_SIZE]; diff --git a/c/cobuild.c b/c/cobuild.c new file mode 100644 index 0000000..9eecbbf --- /dev/null +++ b/c/cobuild.c @@ -0,0 +1,486 @@ +/** +This is an implementation in C of cobuild. See reference implementation in Rust: +https://github.com/cryptape/ckb-transaction-cobuild-poc/blob/main/ckb-transaction-cobuild/src/lib.rs +*/ +// clang-format off +#define CKB_DECLARATION_ONLY +#include +#include +#include +#include +#define MOLECULEC_C2_DECLARATION_ONLY +#define MOLECULEC2_VERSION 6001 +#define MOLECULE2_API_VERSION_MIN 5000 +#include "cobuild.h" +#include "molecule2_reader.h" + +#include "blake2b_decl_only.h" +#include "ckb_consts.h" +#include "ckb_syscall_apis.h" +// clang-format on +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define BLAKE2B_BLOCK_SIZE 32 + +#define CHECK2(cond, code) \ + do { \ + if (!(cond)) { \ + printf("error at %s:%d, error code %d", __FILE__, __LINE__, code); \ + err = code; \ + ASSERT(0); \ + goto exit; \ + } \ + } while (0) + +#define CHECK(_code) \ + do { \ + int code = (_code); \ + if (code != 0) { \ + printf("error at %s:%d, error code %d", __FILE__, __LINE__, code); \ + err = code; \ + ASSERT(0); \ + goto exit; \ + } \ + } while (0) + +enum CobuildErrorCode { + // cobuild error code is from 110 + ERROR_GENERAL = 110, + ERROR_HASH, + ERROR_NONEMPTY_WITNESS, + ERROR_SIGHASHALL_DUP, + ERROR_SIGHASHALL_NOSEAL, +}; + +enum WitnessLayoutId { + WitnessLayoutSighashAll = 4278190081, + WitnessLayoutSighashAllOnly = 4278190082, + WitnessLayoutOtx = 4278190083, + WitnessLayoutOtxStart = 4278190084, +}; + +const char *PERSONAL_SIGHASH_ALL = "ckb-tcob-sighash"; +const char *PERSONAL_SIGHASH_ALL_ONLY = "ckb-tcob-sgohash"; +const char *PERSONAL_OTX = "ckb-tcob-otxhash"; + +/* + The seal cursor uses this data source. So the lifetime of data source should + be long enough. + */ +static uint8_t g_cobuild_seal_data_source[DEFAULT_DATA_SOURCE_LENGTH]; + +#ifdef CKB_C_STDLIB_PRINTF + +static void bin_to_hex(const uint8_t *source, uint8_t *dest, size_t len) { + const static uint8_t HEX_TABLE[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + for (int i = 0; i < len; i++) { + dest[i * 2] = HEX_TABLE[source[i] >> 4]; + dest[i * 2 + 1] = HEX_TABLE[source[i] & 0x0F]; + } +} + +void print_raw_data(const char *name, uint8_t *data, size_t len) { + uint8_t str[924] = {0}; + const int limit = (sizeof(str) - 1) / 2; + if (len > limit) { + printf("The data length (%d) is too long, truncated to %d", len, limit); + len = limit; + } + bin_to_hex(data, str, len); + printf("%s(len=%d): %s", name, len, str); +} + +void print_cursor(const char *name, mol2_cursor_t cursor) { + uint8_t data[256] = {0}; + uint32_t read_len = mol2_read_at(&cursor, data, sizeof(data)); + if (read_len >= sizeof(data)) { + printf("the cursor length (%d) is too long, truncated to %d", cursor.size, + read_len); + } + print_raw_data(name, data, MIN(read_len, sizeof(data))); +} + +// After being enabled, there will be a lot of logs. +#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); + return 0; +} + +#else + +void print_raw_data(const char *name, uint8_t *data, size_t len) {} +void print_cursor(const char *name, mol2_cursor_t cursor) {} +#define BLAKE2B_UPDATE blake2b_update + +#endif + +static void store32(void *dst, uint32_t w) { + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +} + +int ckb_blake2b_init_personal(blake2b_state *S, size_t outlen, + const char *personal) { + blake2b_param P[1]; + + if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32(&P->leaf_length, 0); + store32(&P->node_offset, 0); + store32(&P->xof_length, 0); + P->node_depth = 0; + P->inner_length = 0; + memset(P->reserved, 0, sizeof(P->reserved)); + memset(P->salt, 0, sizeof(P->salt)); + memset(P->personal, 0, sizeof(P->personal)); + for (int i = 0; i < BLAKE2B_PERSONALBYTES; ++i) { + (P->personal)[i] = personal[i]; + } + return blake2b_init_param(S, P); +} + +int new_sighash_all_blake2b(blake2b_state *S) { + return ckb_blake2b_init_personal(S, 32, PERSONAL_SIGHASH_ALL); +} + +int new_sighash_all_only_blake2b(blake2b_state *S) { + return ckb_blake2b_init_personal(S, 32, PERSONAL_SIGHASH_ALL_ONLY); +} + +int new_otx_blake2b(blake2b_state *S) { + return ckb_blake2b_init_personal(S, 32, PERSONAL_OTX); +} + +// for lock script with message, the other witness in script group except first +// one should be empty +int ckb_check_others_in_group() { + int err = ERROR_GENERAL; + for (size_t index = 1;; index++) { + uint64_t witness_len = 0; + err = ckb_load_witness(0, &witness_len, 0, index, CKB_SOURCE_GROUP_INPUT); + if (err == CKB_INDEX_OUT_OF_BOUND) { + err = CKB_SUCCESS; + break; + } + CHECK(err); + // tested by test_non_empty_witness + CHECK2(witness_len == 0, ERROR_NONEMPTY_WITNESS); + } + +exit: + return err; +} + +typedef uint32_t(read_from_t)(uintptr_t arg[], uint8_t *ptr, uint32_t len, + uint32_t offset); + +static uint32_t read_from_witness(uintptr_t arg[], uint8_t *ptr, uint32_t len, + uint32_t offset) { + int err = ERROR_GENERAL; + uint64_t output_len = len; + err = ckb_load_witness(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_cell_data(uintptr_t arg[], uint8_t *ptr, uint32_t len, + uint32_t offset) { + int err; + uint64_t output_len = len; + err = ckb_load_cell_data(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; + } +} + +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) { + cursor->offset = 0; + cursor->size = (uint32_t)total_len; + + mol2_data_source_t *ptr = (mol2_data_source_t *)data_source; + + ptr->read = read_from; + ptr->total_size = total_len; + ptr->args[0] = index; + ptr->args[1] = source; + + ptr->cache_size = 0; + ptr->start_point = 0; + ptr->max_cache_size = cache_len; + + cursor->data_source = ptr; +} + +int ckb_new_witness_cursor(mol2_cursor_t *cursor, uint8_t *data_source, + uint32_t cache_len, size_t index, size_t source) { + int err = ERROR_GENERAL; + uint64_t len = 0; + err = ckb_load_witness(0, &len, 0, index, source); + CHECK(err); + ckb_new_cursor(cursor, len, read_from_witness, data_source, cache_len, index, + source); + +exit: + return err; +} + +int ckb_hash_cursor(blake2b_state *ctx, mol2_cursor_t cursor) { + // one batch to drain whole cache perfectly + // tested by test_input_cell_data_size_0 + // test_input_cell_data_size_1 + // test_input_cell_data_size_2048 + // test_input_cell_data_size_2049 + // test_input_cell_data_size_500k + uint8_t batch[MAX_CACHE_SIZE]; + while (true) { + uint32_t read_len = mol2_read_at(&cursor, batch, sizeof(batch)); + BLAKE2B_UPDATE(ctx, batch, read_len); + // adjust cursor + mol2_add_offset(&cursor, read_len); + mol2_sub_size(&cursor, read_len); + mol2_validate(&cursor); + if (cursor.size == 0) { + break; + } + } + return 0; +} + +static uint32_t try_union_unpack_id(const mol2_cursor_t *cursor, uint32_t *id) { + uint32_t len = mol2_read_at(cursor, (uint8_t *)id, 4); + if (len != 4) { + // tested by: + // tested_by_no_cobuild_append_sighash_all + // tested_by_insert_witness_less_4_before_sighashall + return MOL2_ERR_DATA; + } + return CKB_SUCCESS; +} + +int ckb_fetch_message(bool *has_message, mol2_cursor_t *message_cursor, + uint8_t *data_source, size_t cache_len) { + int err = ERROR_GENERAL; + *has_message = false; + for (size_t index = 0;; index++) { + uint32_t id = 0; + uint64_t len = sizeof(id); + err = ckb_load_witness(&id, &len, 0, index, CKB_SOURCE_INPUT); + if (err == CKB_INDEX_OUT_OF_BOUND) { + err = 0; + break; + } + CHECK(err); + if (len >= sizeof(id) && id == WitnessLayoutSighashAll) { + // tested by: + // tested_by_sighashall_dup + CHECK2(!*has_message, ERROR_SIGHASHALL_DUP); + *has_message = true; + mol2_cursor_t cursor = {0}; + err = ckb_new_witness_cursor(&cursor, data_source, cache_len, index, + CKB_SOURCE_INPUT); + CHECK(err); + mol2_union_t uni = mol2_union_unpack(&cursor); + /* See molecule defintion, the index is 0: + table SighashAll { + message: Message, + seal: Bytes, + } + */ + *message_cursor = mol2_table_slice_by_index(&uni.cursor, 0); + } else { + // there are some possibilities: + // 1. an invalid witness (e.g. empty) + // 2. WitnessArgs + // 3. Other cobuild WitnessLayout(e.g. SighashAllOnly) + // tested by: + // tested_by_append_witnessed_less_than_4 + // tested_by_append_witnessargs + // tested_by_append_other_witnesslayout + } + } +exit: + return err; +} + +int ckb_fetch_seal(mol2_cursor_t *seal_cursor) { + int err = ERROR_GENERAL; + mol2_cursor_t cursor; + err = ckb_new_witness_cursor(&cursor, g_cobuild_seal_data_source, + MAX_CACHE_SIZE, 0, CKB_SOURCE_GROUP_INPUT); + CHECK(err); + uint32_t id = 0; + err = try_union_unpack_id(&cursor, &id); + // when error occurs here, it might be a WitnessArgs layout. It shouldn't be + // cobuild and returns early. + CHECK(err); + if (id == WitnessLayoutSighashAll) { + mol2_union_t uni = mol2_union_unpack(&cursor); + /* See molecule defintion, the index is 1: + table SighashAll { + message: Message, + seal: Bytes, + } + */ + *seal_cursor = mol2_table_slice_by_index(&uni.cursor, 1); + } else if (id == WitnessLayoutSighashAllOnly) { + /* See molecule defintion, the index is 0: + table SighashAllOnly { + seal: Bytes, + } + tested by test_sighash_all_only + */ + mol2_union_t uni = mol2_union_unpack(&cursor); + *seal_cursor = mol2_table_slice_by_index(&uni.cursor, 0); + } else { + // the union id should be SighashAll or SighashAllOnly. otherwise, it fails + // and mark it as non cobuild. + // tested by test_wrong_union_id + printf("error in fetch_seal, id = %u", id); + CHECK2(false, ERROR_SIGHASHALL_NOSEAL); + } + +exit: + return err; +} + +int ckb_generate_signing_message_hash(bool has_message, + mol2_cursor_t message_cursor, + uint8_t *signing_message_hash) { + int err = 0; + // this data source is on stack. When this function returns, all cursors bound + // to this buffer become invalid. + uint8_t data_source[DEFAULT_DATA_SOURCE_LENGTH]; + + blake2b_state ctx; + size_t count = 0; + // use different hash based on message + if (has_message) { + // tested by test_input_cell_data_size_0 + new_sighash_all_blake2b(&ctx); + ckb_hash_cursor(&ctx, message_cursor); + count += message_cursor.size; + } else { + // tested by: + // tested_by_no_has_message + new_sighash_all_only_blake2b(&ctx); + } + + // hash tx hash + uint8_t tx_hash[BLAKE2B_BLOCK_SIZE]; + uint64_t tx_hash_len = sizeof(tx_hash); + err = ckb_load_tx_hash(tx_hash, &tx_hash_len, 0); + CHECK(err); + BLAKE2B_UPDATE(&ctx, tx_hash, sizeof(tx_hash)); + count += 32; + + // hash input cell and data + size_t index = 0; + for (;; index++) { + // default input size is 44 bytes + uint8_t input[128]; + uint64_t input_len = sizeof(input); + err = ckb_load_input(input, &input_len, 0, index, CKB_SOURCE_INPUT); + if (err == CKB_INDEX_OUT_OF_BOUND) { + err = 0; + break; + } + CHECK(err); + BLAKE2B_UPDATE(&ctx, input, input_len); + count += input_len; + + uint64_t cell_data_len = 0; + err = ckb_load_cell_data(0, &cell_data_len, 0, index, CKB_SOURCE_INPUT); + CHECK(err); + mol2_cursor_t cell_data_cursor; + ckb_new_cursor(&cell_data_cursor, cell_data_len, read_from_cell_data, + data_source, MAX_CACHE_SIZE, index, CKB_SOURCE_INPUT); + // only hash as uint32_t. 4 bytes is enough + BLAKE2B_UPDATE(&ctx, &cell_data_len, 4); + count += 4; + err = ckb_hash_cursor(&ctx, cell_data_cursor); + count += cell_data_cursor.size; + CHECK(err); + } + size_t input_len = index; + // hash remaining witnesses + for (size_t index = input_len;; index++) { + uint64_t witness_len = 0; + err = ckb_load_witness(0, &witness_len, 0, index, CKB_SOURCE_INPUT); + if (err == CKB_INDEX_OUT_OF_BOUND) { + err = 0; + break; + } + CHECK(err); + mol2_cursor_t witness_cursor; + ckb_new_cursor(&witness_cursor, witness_len, read_from_witness, data_source, + MAX_CACHE_SIZE, index, CKB_SOURCE_INPUT); + // only hash as uint32_t. 4 bytes is enough + BLAKE2B_UPDATE(&ctx, &witness_len, 4); + count += 4; + err = ckb_hash_cursor(&ctx, witness_cursor); + count += witness_cursor.size; + CHECK(err); + } + blake2b_final(&ctx, signing_message_hash, BLAKE2B_BLOCK_SIZE); + printf("ckb_generate_signing_message_hash total hashed %d bytes", count); + +exit: + return err; +} + +int ckb_parse_message(uint8_t *signing_message_hash, mol2_cursor_t *seal) { + int err = ERROR_GENERAL; + + err = ckb_check_others_in_group(); + // tested by test_non_empty_witness + CHECK(err); + bool has_message = false; + mol2_cursor_t message; + // the message cursor requires longer lifetime of data_source + uint8_t data_source[DEFAULT_DATA_SOURCE_LENGTH]; + err = ckb_fetch_message(&has_message, &message, data_source, MAX_CACHE_SIZE); + CHECK(err); + print_cursor("message", message); + + err = ckb_generate_signing_message_hash(has_message, message, + signing_message_hash); + CHECK(err); + print_raw_data("signing_message_hash", signing_message_hash, 32); + + err = ckb_fetch_seal(seal); + CHECK(err); + print_cursor("seal", *seal); + +exit: + return err; +} diff --git a/c/cobuild.h b/c/cobuild.h new file mode 100644 index 0000000..6e223fd --- /dev/null +++ b/c/cobuild.h @@ -0,0 +1,16 @@ +#ifndef __COBUILD_H__ +#define __COBUILD_H__ + +#include +#include +#include + +#include "molecule2_reader.h" + +/** + * return non-zero if the transaction doesn't have cobuild support. + * signing_message_hash: signing message hash + * seal: the seal. Same as WitnessArgs.lock with new name. + */ +int ckb_parse_message(uint8_t *signing_message_hash, mol2_cursor_t *seal); +#endif diff --git a/c/omni_lock.c b/c/omni_lock.c index 1e092b7..b027a27 100644 --- a/c/omni_lock.c +++ b/c/omni_lock.c @@ -1,6 +1,3 @@ -// uncomment to enable printf in CKB-VM -// #define CKB_C_STDLIB_PRINTF - // it's used by blockchain-api2.h, the behavior when panic #ifndef MOL2_EXIT #define MOL2_EXIT ckb_exit @@ -39,6 +36,7 @@ int ckb_exit(signed char); #include "omni_lock_acp.h" #include "omni_lock_time_lock.h" #include "omni_lock_supply.h" +#include "cobuild.h" // clang-format on @@ -313,26 +311,30 @@ int smt_verify_identity(CkbIdentityType *id, SmtProofEntryVecType *proofs, return err; } -int parse_witness_lock(WitnessLockType *witness_lock) { +int parse_witness_lock(WitnessLockType *witness_lock, mol2_cursor_t *seal) { int err = 0; witness_lock->has_signature = false; witness_lock->has_identity = false; witness_lock->has_proofs = false; - bool witness_existing = false; + mol2_cursor_t mol_lock_bytes = {0}; - WitnessArgsType witness_args; - err = make_witness(&witness_args); - CHECK(err); - witness_existing = witness_args.cur.size > 0; - - // witness or witness lock can be empty if owner lock without omni is used - if (!witness_existing) return err; + if (seal) { + mol_lock_bytes = convert_to_rawbytes(seal); + witness_existing = true; + } else { + WitnessArgsType witness_args; + err = make_witness(&witness_args); + CHECK(err); + witness_existing = witness_args.cur.size > 0; - BytesOptType mol_lock = witness_args.t->lock(&witness_args); - if (mol_lock.t->is_none(&mol_lock)) return err; + // witness or witness lock can be empty if owner lock without omni is used + if (!witness_existing) return err; - mol2_cursor_t mol_lock_bytes = mol_lock.t->unwrap(&mol_lock); + BytesOptType mol_lock = witness_args.t->lock(&witness_args); + if (mol_lock.t->is_none(&mol_lock)) return err; + mol_lock_bytes = mol_lock.t->unwrap(&mol_lock); + } // convert Bytes to OmniLockWitnessLock OmniLockWitnessLockType mol_witness_lock = make_OmniLockWitnessLock(&mol_lock_bytes); @@ -396,8 +398,22 @@ int main() { // args (args.id) CkbIdentityType identity = {0}; - err = parse_witness_lock(&witness_lock); + mol2_cursor_t seal = {0}; + /* + * When it fails, WitnessArgs is used. No cobuild enabled. + */ + err = ckb_parse_message(g_cobuild_signing_message_hash, &seal); + if (err) { + printf("cobuild disabled"); + g_cobuild_enabled = false; + err = parse_witness_lock(&witness_lock, NULL); + } else { + printf("cobuild enabled"); + g_cobuild_enabled = true; + err = parse_witness_lock(&witness_lock, &seal); + } CHECK(err); + printf("parse_witness_lock done"); err = parse_args(&args); CHECK(err); diff --git a/c/top_level.mol b/c/top_level.mol new file mode 100644 index 0000000..7ab2ad3 --- /dev/null +++ b/c/top_level.mol @@ -0,0 +1,8 @@ +import basic; + +union WitnessLayout { + SighashAll: 4278190081, + SighashAllOnly: 4278190082, + Otx: 4278190083, + OtxStart: 4278190084, +} diff --git a/deps/ckb-c-stdlib-20210801 b/deps/ckb-c-stdlib-20210801 index 20578df..66dc8e3 160000 --- a/deps/ckb-c-stdlib-20210801 +++ b/deps/ckb-c-stdlib-20210801 @@ -1 +1 @@ -Subproject commit 20578dfb092b3b3761df755395e20ec142a83d6e +Subproject commit 66dc8e3b30c484ee499c9d93235d7713631897fe diff --git a/test-vectors/README.md b/test-vectors/README.md new file mode 100644 index 0000000..582d494 --- /dev/null +++ b/test-vectors/README.md @@ -0,0 +1,3 @@ + +These test vectors require [ckb-debugger](https://github.com/nervosnetwork/ckb-standalone-debugger.git) installed. +Use shell script `run-all.sh` to run all scripts. diff --git a/test-vectors/run-all.sh b/test-vectors/run-all.sh new file mode 100644 index 0000000..51e4f1a --- /dev/null +++ b/test-vectors/run-all.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +for file in *.json; do + ckb-debugger --bin ../build/omni_lock -f $file -i 0 -s lock +done + diff --git a/test-vectors/tx_btc_P2PKH_compressed.json b/test-vectors/tx_btc_P2PKH_compressed.json new file mode 100644 index 0000000..f5d94ba --- /dev/null +++ b/test-vectors/tx_btc_P2PKH_compressed.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0xdea9fe01c9ac44bf67e256ddbda8aa38cceab479d5e9a258d082c6f947dfe976", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x04fe5ee37ff7962f1661615c1f7b57d728e15e5e1d00" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0xe6b26aebbec9c2b0eb56a0908ec4d8d1c18ad8b85479e3e2040de5cb4ed09c79", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x8a7362467938fbc5dfc0db411190d84ac0ba5484840c210fe9def994136da4b9", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x570f24c51006d012a49edca8224600fc40acb1de65e0845d4637bbb817a44f9a", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0xe6b26aebbec9c2b0eb56a0908ec4d8d1c18ad8b85479e3e2040de5cb4ed09c79", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x8a7362467938fbc5dfc0db411190d84ac0ba5484840c210fe9def994136da4b9", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x570f24c51006d012a49edca8224600fc40acb1de65e0845d4637bbb817a44f9a", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0xdea9fe01c9ac44bf67e256ddbda8aa38cceab479d5e9a258d082c6f947dfe976", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d00000055000000550000001000000055000000550000004100000020f7d2be56af39715ad504b8efee1d452b51c374e6403b8a26e71f761814c84fa94ab7cfe84fa8a3d681e7bc88908654c707f13ddcdc25fd69982501ffd8c57ce920000000cd750bd601b71570de98e60a0d29f25cb4952e474357f6f4e562ee11b465f6b0" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_btc_P2PKH_uncompressed.json b/test-vectors/tx_btc_P2PKH_uncompressed.json new file mode 100644 index 0000000..7a59c9c --- /dev/null +++ b/test-vectors/tx_btc_P2PKH_uncompressed.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0x05046fcd76a480b41e19f809e4d07a0357e1ced3584351bcf0e73df7c555da4e", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x0481ed18ea9760cbce2e1d08df6e902a246a94d01e00" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0x4bffda352ef79c5cc6f642544977a4d09ee06d5e5e48f151a7b0a29523e4deac", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa0b74c6aab7a2e4f4b17780c3aebae9f77394ad7e61b035864443f02c82acf10", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xf658c925dbb6667639b1a2fddf838390fb3a0756ec87a12b9e31cd9c104207f0", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0x4bffda352ef79c5cc6f642544977a4d09ee06d5e5e48f151a7b0a29523e4deac", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa0b74c6aab7a2e4f4b17780c3aebae9f77394ad7e61b035864443f02c82acf10", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xf658c925dbb6667639b1a2fddf838390fb3a0756ec87a12b9e31cd9c104207f0", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0x05046fcd76a480b41e19f809e4d07a0357e1ced3584351bcf0e73df7c555da4e", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d0000005500000055000000100000005500000055000000410000001babece9ad42f96159eadd0d85e9fc7270181b0b53bf18844546e0483e1e4d69e63de00f348e662988c2b9747c05e7eb1d3f680c08cbf0eee6aeeae78f5926356420000000fbce361e03e3a60d3cda33a704b3b705663454e3e9c012647378cfe029ed6464" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_btc_Segwit_Bech32.json b/test-vectors/tx_btc_Segwit_Bech32.json new file mode 100644 index 0000000..5d72eb6 --- /dev/null +++ b/test-vectors/tx_btc_Segwit_Bech32.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0x128ffc9f7bb137088f3731864810925d6833e26477a7f36363f5e55f58b7776c", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x04b19c301d73f66c5e9ec886d91e0832cde8f778ce00" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa8433dac5579b99ae428cee6fab72092fc19367bb2be79d0dc517de41f7462e2", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x31eccfa8eb39b832a0d906fc78ebaa10011d19f22ea7091ba5309feb25616cdd", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xeed77a312e4a4331b9f372007aa129b6f2803f01d99116437652e058302100a4", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0xa8433dac5579b99ae428cee6fab72092fc19367bb2be79d0dc517de41f7462e2", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x31eccfa8eb39b832a0d906fc78ebaa10011d19f22ea7091ba5309feb25616cdd", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xeed77a312e4a4331b9f372007aa129b6f2803f01d99116437652e058302100a4", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0x128ffc9f7bb137088f3731864810925d6833e26477a7f36363f5e55f58b7776c", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d000000550000005500000010000000550000005500000041000000289b023f11132b0cede5c301eae6cd557b0232202a9ed55d0ea3531eada142645144fbdbecf36ea866c3a5e64ec85ab41d4c7dc72689ec727bc56fb165aee6af102000000048a3ddad43f843536592c8dd5715f20d6a01bf008be315cc8a0f63bca84be408" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_btc_Segwit_P2SH.json b/test-vectors/tx_btc_Segwit_P2SH.json new file mode 100644 index 0000000..78467b3 --- /dev/null +++ b/test-vectors/tx_btc_Segwit_P2SH.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0xee4f5ba9dd3a9d240ca144ac1db631ad5c0859f953c1f46acd2eab27330d485d", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x046939b8ddba1008fa4b5152f4d7ab9542d15df92900" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0xeab2ed467d69b80d4fa948b6806408d13e37cc115df2d9e9af3e858c719e8671", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x80fbb790af25fd12cd4c0350d9f2d09912106c66f1a2b25e66dad05257dbc9ef", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x66793107b02105606fee1f99e9f9d37fbbbba11410235ceea54764e31d1f8615", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0xeab2ed467d69b80d4fa948b6806408d13e37cc115df2d9e9af3e858c719e8671", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x80fbb790af25fd12cd4c0350d9f2d09912106c66f1a2b25e66dad05257dbc9ef", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x66793107b02105606fee1f99e9f9d37fbbbba11410235ceea54764e31d1f8615", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0xee4f5ba9dd3a9d240ca144ac1db631ad5c0859f953c1f46acd2eab27330d485d", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d00000055000000550000001000000055000000550000004100000023618f3520abbe36565e31c63ceb47a3e107259810c97e75c67e385672e47174af619f9fca4a889123bf39e82ba045984bc43e6b04a9e752964af495dab9f27f48200000002da4f277a82d8311315e40995252ec6445240004e3105262ad6bd9a62ea31c83" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_cobuild_btc_compressed.json b/test-vectors/tx_cobuild_btc_compressed.json new file mode 100644 index 0000000..ad11366 --- /dev/null +++ b/test-vectors/tx_cobuild_btc_compressed.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0xd1e44a0ecd92ce90ec215f5d236ceb255247be49c5e7a22658c73eba05fef514", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x04bc6e317199b3207c5589ffae4aed3570208cb62b00" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0xcd606c347e9435c42fca6c31dd8cc1aa25cdc28a7a25ba79bca894099bf7b70e", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xe1780a4705c72e853f2330486714b705a9845ed63306c82505c1d84864152159", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x75873c7509465e77c3a306d0ceb263a7c39279edf2861928f875001c3e1584ef", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0xcd606c347e9435c42fca6c31dd8cc1aa25cdc28a7a25ba79bca894099bf7b70e", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xe1780a4705c72e853f2330486714b705a9845ed63306c82505c1d84864152159", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x75873c7509465e77c3a306d0ceb263a7c39279edf2861928f875001c3e1584ef", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0xd1e44a0ecd92ce90ec215f5d236ceb255247be49c5e7a22658c73eba05fef514", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x010000ff710000000c000000180000000c00000008000000040000005500000055000000100000005500000055000000410000001fdf92875c7130e347da5d09f56332893c0bffc1655b4b57c59610d0a4ea36c05838b90918afc54c88e9b1624f3465deb2aff93c24790e7d51f8cdb2712bfc6024" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_eth.json b/test-vectors/tx_eth.json new file mode 100644 index 0000000..d78eecd --- /dev/null +++ b/test-vectors/tx_eth.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0x44e6de084ee13cf884f71864fdb3aafb4398a87ae6b0345b7f1d77bb44bca7b0", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x01840cb79096ecbed6ebbdb181f89825da5a73566200" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0xd79fc373c88056e9cd1865613bb0a2cda756dabbc65234b4ef8ee7ad3c011657", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x8173219326f1b748840631d7535ffd54b1c8d605a3b045f8db3583f9601ca8f3", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x41b38d4d1a6c93f6da1b0106ff590a31bbdb5dec539f486984f8305c4c047c64", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0xd79fc373c88056e9cd1865613bb0a2cda756dabbc65234b4ef8ee7ad3c011657", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x8173219326f1b748840631d7535ffd54b1c8d605a3b045f8db3583f9601ca8f3", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x41b38d4d1a6c93f6da1b0106ff590a31bbdb5dec539f486984f8305c4c047c64", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0x44e6de084ee13cf884f71864fdb3aafb4398a87ae6b0345b7f1d77bb44bca7b0", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d000000550000005500000010000000550000005500000041000000fbe1e03e98c37cd1e7135b7b072696463a8bab5ae1dc5ae84710b5c5f6cf4410131fa2bc5e70df768e14f3555c53064b0416cda285f6b675e139ea6ae36593ab012000000051cd14e79750652e9fbb84ec65dcabe8b6b40a66902fdd9f9d0a763019c82c82" + ] + } +} \ No newline at end of file diff --git a/test-vectors/tx_eth_displaying.json b/test-vectors/tx_eth_displaying.json new file mode 100644 index 0000000..876ca3a --- /dev/null +++ b/test-vectors/tx_eth_displaying.json @@ -0,0 +1,174 @@ +{ + "mock_info": { + "inputs": [ + { + "input": { + "since": "0x0", + "previous_output": { + "tx_hash": "0x84757cec14a387aa66dc3ceb22659e9ebc7713be555061a303930ce34495cffc", + "index": "0x0" + } + }, + "output": { + "capacity": "0x2a", + "lock": { + "code_hash": "0x519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + "hash_type": "data", + "args": "0x122d5b9c9de18c04b74515dc0a709b2087d88cbde000" + }, + "type": null + }, + "data": "0x", + "header": null + } + ], + "cell_deps": [ + { + "cell_dep": { + "out_point": { + "tx_hash": "0x3b12c8cf1699a49f4a9404d073e5fe777ccbaae32157103007a145dd1dcc231a", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xb627b19f800", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xc46c5af6c53bf4cb63c437092c68ca5d937b5e612b253e0ad0c901500509e71a", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0xbebc20000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/always_success }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0x338744a588ad05210c671c619e42a4a8679409696786feb870f32bc731f51320", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x5f5e10000000", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + }, + "data": "0x{{ data ../build/secp256k1_data_20210801 }}", + "header": null + }, + { + "cell_dep": { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + }, + "output": { + "capacity": "0x11510", + "lock": { + "code_hash": "0xd483925160e4232b2cb29f012e8380b7b612d71cf4e79991476b6bcf610735f6", + "hash_type": "data", + "args": "0x" + }, + "type": { + "code_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "hash_type": "type", + "args": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "data": "0x{{ data ../build/validate_signature_rsa }}", + "header": null + } + ], + "header_deps": [], + "extensions": [] + }, + "tx": { + "version": "0x0", + "cell_deps": [ + { + "out_point": { + "tx_hash": "0x3b12c8cf1699a49f4a9404d073e5fe777ccbaae32157103007a145dd1dcc231a", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xc46c5af6c53bf4cb63c437092c68ca5d937b5e612b253e0ad0c901500509e71a", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0x338744a588ad05210c671c619e42a4a8679409696786feb870f32bc731f51320", + "index": "0x0" + }, + "dep_type": "code" + }, + { + "out_point": { + "tx_hash": "0xa638f65f650bdac13bf91134ed7eec8feded1dac5e6add9e26cf658b2a693066", + "index": "0x0" + }, + "dep_type": "code" + } + ], + "header_deps": [], + "inputs": [ + { + "since": "0x0", + "previous_output": { + "tx_hash": "0x84757cec14a387aa66dc3ceb22659e9ebc7713be555061a303930ce34495cffc", + "index": "0x0" + } + } + ], + "outputs": [ + { + "capacity": "0x2a", + "lock": { + "code_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "hash_type": "data", + "args": "0x" + }, + "type": null + } + ], + "outputs_data": [ + "0x" + ], + "witnesses": [ + "0x8d00000010000000690000008d000000550000005500000010000000550000005500000041000000722f2d6b6ccefaec16a754fbdc2cae8390ab8e3a4f54cf24ecfd95663c96a27027865a7d8ee2b96bda3dea2670fea821aac5dae8e7cf6c345366b98ce94c7cfa00200000007d5c4db4aad6fd65329c1b812fabfb8ffe8a31a0db22109ae54489a4a41dd713" + ] + } +} \ No newline at end of file diff --git a/tests/omni_lock/omni_lock_sim.c b/tests/omni_lock/omni_lock_sim.c index 42c9770..9e797d0 100644 --- a/tests/omni_lock/omni_lock_sim.c +++ b/tests/omni_lock/omni_lock_sim.c @@ -16,6 +16,11 @@ void debug_print_hex(const char* prefix, const uint8_t* buf, size_t length) { printf("\n"); } +int ckb_parse_message(uint8_t* signing_message_hash, mol2_cursor_t* seal) { + // not cobuild + return 1; +} + /* hex2bin modified from * https://chromium.googlesource.com/chromium/deps/xz/+/77022065014d48cf51d83322264ab4836fd175ec/debug/hex2bin.c */ diff --git a/tests/omni_lock_rust/Cargo.lock b/tests/omni_lock_rust/Cargo.lock index 00d109c..cce8450 100644 --- a/tests/omni_lock_rust/Cargo.lock +++ b/tests/omni_lock_rust/Cargo.lock @@ -3,19 +3,19 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "addr2line" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] [[package]] -name = "aho-corasick" -version = "0.6.10" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -dependencies = [ - "memchr 2.7.1", -] +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "anyhow" @@ -38,11 +38,32 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bit-vec" -version = "0.5.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" @@ -58,9 +79,9 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "blake2b-ref" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95916998c798756098a4eb1b3f2cd510659705a9817bf203d61abd30fbec3e7b" +checksum = "294d17c72e0ba59fad763caa112368d0672083779cdebbb97164f4bb4c1e339a" [[package]] name = "blake2b-rs" @@ -71,6 +92,16 @@ dependencies = [ "cc", ] +[[package]] +name = "blake2b-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89a8565807f21b913288968e391819e7f9b2f0f46c7b89549c051cccf3a2771" +dependencies = [ + "cc", + "cty", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -111,6 +142,33 @@ dependencies = [ "serde", ] +[[package]] +name = "cacache" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142316461ed3a3dfcba10417317472da5bfd0461e4d276bf7c07b330766d9490" +dependencies = [ + "digest 0.10.7", + "either", + "futures", + "hex", + "libc", + "memmap2", + "miette", + "reflink-copy", + "serde", + "serde_derive", + "serde_json", + "sha1", + "sha2", + "ssri", + "tempfile", + "thiserror", + "tokio", + "tokio-stream", + "walkdir", +] + [[package]] name = "cc" version = "1.0.83" @@ -134,16 +192,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ckb-chain-spec" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6545c270115cdbed0b5ec452a4ef8753dac8990ac0996110531041a00f0842f9" +checksum = "210df338c83691c2173136656c411c3fe09578a66377a05014956419bede76cf" dependencies = [ + "cacache", "ckb-constant", "ckb-crypto", "ckb-dao-utils", "ckb-error", "ckb-hash", "ckb-jsonrpc-types", + "ckb-logger", "ckb-pow", "ckb-rational", "ckb-resource", @@ -155,24 +215,24 @@ dependencies = [ [[package]] name = "ckb-channel" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0048e1732dc769525b332a20a4eb0942f84e1ba3cbcbcb286dacd3a585f6e50a" +checksum = "50d21e6d4ad47858609ced9d887e63e821ba6770f28e7be58e8d56213a0d0924" dependencies = [ "crossbeam-channel", ] [[package]] name = "ckb-constant" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237ea9a8e7ced2731a46bbbf23b40a7df4c5229bb2226396ba70bfe4cdc85e3c" +checksum = "b42093e370876b71569292fc0aa9ae1078114ee678c4e4b4ae77a81b590fdba7" [[package]] name = "ckb-crypto" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c69f679e843fae7294679efdbe6239aaf9469a40f0b3145e075708879b26513" +checksum = "35ed640e73c39b5e0fc8a39c6d013733761023424e2bc70dafd74d92ce6c36cb" dependencies = [ "ckb-fixed-hash", "faster-hex 0.6.1", @@ -184,9 +244,9 @@ dependencies = [ [[package]] name = "ckb-dao-utils" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915bbb801dee8f14e47714b18b8c8216c574156c7a1bd922fba2f73d73a8f10a" +checksum = "aaf9300f9b1ff36e576ca6ed374ec9704f6da6f61492ea48038ff0b9067c2779" dependencies = [ "byteorder", "ckb-error", @@ -195,9 +255,9 @@ dependencies = [ [[package]] name = "ckb-error" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945d804f5648bd3060b0d19336952093f3bbc6cc568533230156d5f579fef24c" +checksum = "9948a60c3fa47131ec9907cfb64c94e4fd9199ef9329ba0ba4d53b8e03adfbbe" dependencies = [ "anyhow", "ckb-occupied-capacity", @@ -207,9 +267,9 @@ dependencies = [ [[package]] name = "ckb-fixed-hash" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e74fcc7ab5e6274991cdd7b3a49583b45f63c1d82cda639edd259d7cf73bd2" +checksum = "0629983e05127c5bbf025cefdac36a91c3a0720acf1b2e2637ff1f0ac673a78c" dependencies = [ "ckb-fixed-hash-core", "ckb-fixed-hash-macros", @@ -217,9 +277,9 @@ dependencies = [ [[package]] name = "ckb-fixed-hash-core" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b845d71fee1b55f68453c8db69b54a43db1370147f0f79909324eaf030a28e2e" +checksum = "c582d7d52e96ce65c2995a7f399c6dc3f314fec64dd15d47ec903896ac24a428" dependencies = [ "faster-hex 0.6.1", "serde", @@ -228,9 +288,9 @@ dependencies = [ [[package]] name = "ckb-fixed-hash-macros" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff13f0f845ae9fb1073239094e6cadaf7af213181e7462df4f73cdb81d6b5ee6" +checksum = "3bae4184f70cbd2e36839d902f403f06ea6a009df67ac2f7d37942890459618c" dependencies = [ "ckb-fixed-hash-core", "proc-macro2", @@ -238,21 +298,53 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ckb-gdb-remote-protocol" +version = "0.113.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e61a48efbbdbbbbf8811d221226b3c74058e7f1d64ea3ae5dae8604ba85d7eda" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "log", + "memchr 2.7.1", + "nom", + "num-derive", + "num-traits", + "strum", + "strum_macros", +] + +[[package]] +name = "ckb-gen-types" +version = "0.113.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c709b63557041d03db0bc09b56ddc95de455ea555d537d5599117163f095973c" +dependencies = [ + "cfg-if 1.0.0", + "ckb-error", + "ckb-fixed-hash", + "ckb-hash", + "ckb-occupied-capacity", + "molecule", + "numext-fixed-uint", +] + [[package]] name = "ckb-hash" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f409236f9c815cebf15dea49924bf3f316d47682f710fa9493135993a57d7913" +checksum = "b78504239eedf043013a4c1d5a3cf38a2917ef37643c3608ff4183aa2888f48f" dependencies = [ "blake2b-ref", - "blake2b-rs", + "blake2b-rs 0.2.0", ] [[package]] name = "ckb-jsonrpc-types" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b11f78288ab8f299caf7b316706ca41d8b7a67a5e20719245d584230dce003" +checksum = "97cf7e01a18fb980f3d993fafdf06999379b71ebca098196ed42824bab0b3d9d" dependencies = [ "ckb-types", "faster-hex 0.6.1", @@ -262,18 +354,27 @@ dependencies = [ [[package]] name = "ckb-logger" -version = "0.100.0-rc2" +version = "0.113.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f5f89647d0d71aef57cafc580c8ca770b1e7afa85400c29de10c6d6a5d2adc" +dependencies = [ + "log", +] + +[[package]] +name = "ckb-merkle-mountain-range" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14feffc8b90fd0e5dead8b8c0609faf5e6b5f3c06ceb487b8f0c91f378dc92cf" +checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" dependencies = [ - "log 0.4.20", + "cfg-if 1.0.0", ] [[package]] name = "ckb-occupied-capacity" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a42877e9e929241d9965b8fa0337c3dc93715c452df0c305f4a6cceda4ecdda" +checksum = "bfe678c0047869c71ae01369ada83ebb43567504c3c5e338a64dcd679b98ecad" dependencies = [ "ckb-occupied-capacity-core", "ckb-occupied-capacity-macros", @@ -281,18 +382,18 @@ dependencies = [ [[package]] name = "ckb-occupied-capacity-core" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80447a92eeef022f9dff53413d46900cbab5a8e28bd5ef49c88512a3b8aa5d6d" +checksum = "35dba70fddc9eda1906875b4c99b14d64910a429a58972658e8f65930f77f27b" dependencies = [ "serde", ] [[package]] name = "ckb-occupied-capacity-macros" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab646c39f21c297ce0fd274bfe27361830adf2d64d0f15b2ef320dea2001cb5" +checksum = "1a37efa3314fc8d1b6ead861743e7012126204449a7c6579f0e571a3456d0d34" dependencies = [ "ckb-occupied-capacity-core", "quote 1.0.35", @@ -301,23 +402,23 @@ dependencies = [ [[package]] name = "ckb-pow" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b034068b7746d5cc666c95fcdaf355bd9c302f3d68207e9c6e988e7307c8ad" +checksum = "c28156a3ea6941bad362f0de75a2358bc759f52d505b4cfae0db223e25646fdd" dependencies = [ "byteorder", "ckb-hash", "ckb-types", "eaglesong", - "log 0.4.20", + "log", "serde", ] [[package]] name = "ckb-rational" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80648e2f04b2429c96497dfd786edbbaabcde45d3f566ef96bb84c6fe1c3999c" +checksum = "a0d64ef7e9b0785e1b2acdc1a96072bbdefa6ac72bca36de91d9d9e65cd39bbd" dependencies = [ "numext-fixed-uint", "serde", @@ -325,9 +426,9 @@ dependencies = [ [[package]] name = "ckb-resource" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21111aa1eaf33e998163bdc35bb01a22cb5a71660a8c694dbaaa7455668807e1" +checksum = "ea0c9ca6ccc86e4ed3f49c3dc05b1bd58f27205cb9ded891b86995a9edd06974" dependencies = [ "ckb-system-scripts", "ckb-types", @@ -335,15 +436,14 @@ dependencies = [ "includedir_codegen", "phf", "serde", - "tempfile", "walkdir", ] [[package]] name = "ckb-script" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c9aa8b59733bbf92195d9596a24e369db27614593b522582ab24e2436c255c" +checksum = "ec56fceeff7d1fb5229bf03af876360dabf7f9da7eab67a3ce5164c09b4a90d4" dependencies = [ "byteorder", "ckb-chain-spec", @@ -353,19 +453,17 @@ dependencies = [ "ckb-traits", "ckb-types", "ckb-vm", - "ckb-vm-definitions", "faster-hex 0.6.1", - "goblin 0.2.3", "serde", ] [[package]] name = "ckb-system-scripts" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfbce46ad2de7563c7e456888d4a29df3d461106a989836c08627d044409e928" +checksum = "fa5c59063142de7a68cfad4449c6b3863563856219a2925dfb8c5f019ec2aa47" dependencies = [ - "blake2b-rs", + "blake2b-rs 0.2.0", "faster-hex 0.6.1", "includedir", "includedir_codegen", @@ -374,40 +472,44 @@ dependencies = [ [[package]] name = "ckb-traits" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8629d61183ab240fe0c598b5723c16bc9741691df2261574ff04c6fb87cb070d" +checksum = "a4fe215ac785af5f9011aeae14f6f1b05d8cad7ca76a98fe97bf374650e07ccc" dependencies = [ "ckb-types", ] [[package]] name = "ckb-types" -version = "0.100.0-rc2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31588d3154ce8e3bd7d815b6e8223afecbcf3ca05a58a26db371393eb0ffe42a" +checksum = "eb8a1e28eeb4bc18dfc0e97306147d1c9399ffab6292185346a2af2983ed80f3" dependencies = [ "bit-vec", - "bitflags 1.3.2", "bytes", "ckb-channel", + "ckb-constant", "ckb-error", "ckb-fixed-hash", + "ckb-gen-types", "ckb-hash", + "ckb-merkle-mountain-range", "ckb-occupied-capacity", "ckb-rational", "derive_more", + "golomb-coded-set", "merkle-cbt", "molecule", "numext-fixed-uint", "once_cell", + "paste", ] [[package]] name = "ckb-vm" -version = "0.20.0-rc2" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3edaa6828e414b2d8cf773acaa561fd104ac595028de9326df790a1f7ba40f8" +checksum = "0cc004a826b9bc9319ffae0b8415690e1b5f1482266d55fbd43843aa40ddcd63" dependencies = [ "byteorder", "bytes", @@ -416,8 +518,6 @@ dependencies = [ "derive_more", "goblin 0.2.3", "goblin 0.4.0", - "libc", - "mapr", "rand 0.7.3", "scroll", "serde", @@ -425,24 +525,29 @@ dependencies = [ [[package]] name = "ckb-vm-debug-utils" -version = "0.1.0" -source = "git+https://github.com/nervosnetwork/ckb-vm-debug-utils.git?rev=f72995f#f72995fc02f665aef356c81c3e0d5030fdac88c2" +version = "0.113.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33089605fd91dc88adb60f8ad4e3536004067cfd4fe4040349ece6c925a386e3" dependencies = [ "byteorder", "bytes", + "ckb-gdb-remote-protocol", "ckb-vm", - "env_logger", - "gdb-remote-protocol", + "gdbstub", + "gdbstub_arch", "libc", - "log 0.4.20", + "log", "nix", ] [[package]] name = "ckb-vm-definitions" -version = "0.20.1" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45af9be584526f91e1517739802d0ebf82eb8d14853c45128ce930144a171ddd" +checksum = "c4ced3ff9d79b53d93c106720f6c1f855694290e33581850e05c859500eee83f" +dependencies = [ + "paste", +] [[package]] name = "cloudabi" @@ -479,22 +584,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.6.6" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -dependencies = [ - "cfg-if 0.1.10", - "lazy_static", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -506,6 +607,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + [[package]] name = "derive_more" version = "0.99.17" @@ -545,26 +652,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d978bd5d343e8ab9b5c0fc8d93ff9c602fdc96616ffff9c05ac7a155419b824" [[package]] -name = "env_logger" -version = "0.4.3" +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "log 0.3.9", - "regex", + "libc", + "windows-sys", ] [[package]] name = "faster-hex" -version = "0.3.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b8cccaafb5aae8c282692e5590f341925edea6c696e8715ff0d973320b2646" +checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" [[package]] name = "faster-hex" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" +dependencies = [ + "serde", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "flate2" @@ -597,17 +719,130 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote 1.0.35", + "syn 2.0.48", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr 2.7.1", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "gdb-remote-protocol" version = "0.1.0" source = "git+https://github.com/luser/rust-gdb-remote-protocol?rev=565ab0c#565ab0c0ac189c82b0e7df217860599fc1ae6287" dependencies = [ - "log 0.4.20", + "log", "nom", "strum", "strum_macros", ] +[[package]] +name = "gdbstub" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e02bf1b1a624d96925c608f1b268d82a76cbc587ce9e59f7c755e9ea11c75c" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "log", + "managed", + "num-traits", + "paste", +] + +[[package]] +name = "gdbstub_arch" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eecb536c55c43593a00dde9074dbbdb0e81ce5f20dbca921400f8779c21dea9c" +dependencies = [ + "gdbstub", + "num-traits", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -629,13 +864,19 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "goblin" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" dependencies = [ - "log 0.4.20", + "log", "plain", "scroll", ] @@ -646,11 +887,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "532a09cd3df2c6bbfc795fb0434bff8f22255d1d07328180e918a2e6ce122d4d" dependencies = [ - "log 0.4.20", + "log", "plain", "scroll", ] +[[package]] +name = "golomb-coded-set" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7076c0cd6257d84b785b0f22c36443dd47a5e86a1256d7ef82c8cb88ea9a7e" +dependencies = [ + "siphasher", +] + [[package]] name = "heapsize" version = "0.4.2" @@ -668,9 +918,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "includedir" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97402f770a519ebea51b27131c3b6558cfd2375aff21294bad806bad91bf0b6" +checksum = "afd126bd778c00c43a9dc76d1609a0894bf4222088088b2217ccc0ce9e816db7" dependencies = [ "flate2", "phf", @@ -678,9 +928,9 @@ dependencies = [ [[package]] name = "includedir_codegen" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7d542be113fd84855692fb536c16cc4c09527724d1dca8953047d71cccadef" +checksum = "0ac1500c9780957c9808c4ec3b94002f35aab01483833f5a8bce7dfb243e3148" dependencies = [ "flate2", "phf_codegen", @@ -715,13 +965,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] -name = "log" -version = "0.3.9" +name = "linux-raw-sys" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.20", -] +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "log" @@ -730,14 +977,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] -name = "mapr" +name = "managed" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a28a55dbc005b2f6f123c4058933d57add373d362f6fd3a76aab4fe6973500" -dependencies = [ - "libc", - "winapi", -] +checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" [[package]] name = "memchr" @@ -754,6 +997,24 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "merkle-cbt" version = "0.3.2" @@ -763,6 +1024,29 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "miette" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" +dependencies = [ + "miette-derive", + "once_cell", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +dependencies = [ + "proc-macro2", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -774,9 +1058,9 @@ dependencies = [ [[package]] name = "molecule" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58d1147f4d0d51ce72c56a6099ae5dbfd007b250271bb965f82dd10fca2bf02" +checksum = "d4fd9767ab5e5f2ea40f71ff4c8bdb633c50509052e093c2fdd0e390a749dfa3" dependencies = [ "bytes", "cfg-if 1.0.0", @@ -785,15 +1069,15 @@ dependencies = [ [[package]] name = "nix" -version = "0.15.0" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "void", + "memoffset", + "pin-utils", ] [[package]] @@ -805,6 +1089,26 @@ dependencies = [ "memchr 1.0.2", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote 1.0.35", + "syn 1.0.109", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "numext-constructor" version = "0.1.6" @@ -851,11 +1155,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr 2.7.1", +] + [[package]] name = "omni-lock-test" version = "0.1.0" dependencies = [ - "blake2b-rs", + "blake2b-ref", + "blake2b-rs 0.1.5", "ckb-chain-spec", "ckb-crypto", "ckb-error", @@ -865,11 +1179,11 @@ dependencies = [ "ckb-types", "ckb-vm", "ckb-vm-debug-utils", - "faster-hex 0.3.1", + "faster-hex 0.9.0", "gdb-remote-protocol", "hex", - "includedir_codegen", "lazy_static", + "molecule", "openssl", "rand 0.6.5", "ripemd", @@ -928,20 +1242,26 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "phf" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ "phf_generator", "phf_shared", @@ -949,23 +1269,35 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ "phf_shared", - "rand 0.6.5", + "rand 0.7.3", ] [[package]] name = "phf_shared" -version = "0.7.24" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" dependencies = [ "siphasher", ] +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.28" @@ -1176,39 +1508,22 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -dependencies = [ - "aho-corasick", - "memchr 2.7.1", - "regex-syntax", - "thread_local", - "utf8-ranges", -] - -[[package]] -name = "regex-syntax" -version = "0.5.6" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "ucd-util", + "bitflags 1.3.2", ] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "reflink-copy" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "767be24c0da52e7448d495b8d162506a9aa125426651d547d545d6c2b4b65b62" dependencies = [ - "winapi", + "cfg-if 1.0.0", + "rustix", + "windows", ] [[package]] @@ -1220,6 +1535,12 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1229,6 +1550,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.16" @@ -1266,18 +1600,18 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.19.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.3.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" dependencies = [ "cc", ] @@ -1319,6 +1653,28 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.8" @@ -1344,19 +1700,45 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.2.3" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "sparse-merkle-tree" version = "0.5.2-rc1" source = "git+https://github.com/nervosnetwork/sparse-merkle-tree.git?rev=2dce546#2dce546eab6f7eaaab3a0886247fd12ac798ad28" dependencies = [ - "blake2b-rs", + "blake2b-rs 0.1.5", "cfg-if 0.1.10", ] +[[package]] +name = "ssri" +version = "9.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7a2b3c2bc9693bcb40870c4e9b5bf0d79f9cb46273321bf855ec513e919082" +dependencies = [ + "base64", + "digest 0.10.7", + "hex", + "miette", + "serde", + "sha-1", + "sha2", + "thiserror", + "xxhash-rust", +] + [[package]] name = "strum" version = "0.8.0" @@ -1417,16 +1799,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ - "cfg-if 0.1.10", - "libc", - "rand 0.7.3", + "cfg-if 1.0.0", + "fastrand", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys", ] [[package]] @@ -1450,12 +1831,37 @@ dependencies = [ ] [[package]] -name = "thread_local" -version = "0.3.6" +name = "tokio" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ - "lazy_static", + "backtrace", + "bytes", + "pin-project-lite", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote 1.0.35", + "syn 2.0.48", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] @@ -1473,12 +1879,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ucd-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd2fc5d32b590614af8b0a20d837f32eca055edd0bbead59a9cfe80858be003" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -1486,16 +1886,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-xid" -version = "0.0.4" +name = "unicode-width" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] -name = "utf8-ranges" -version = "1.0.5" +name = "unicode-xid" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" [[package]] name = "vcpkg" @@ -1509,12 +1909,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "walkdir" version = "2.4.0" @@ -1561,3 +1955,94 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "xxhash-rust" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" diff --git a/tests/omni_lock_rust/Cargo.toml b/tests/omni_lock_rust/Cargo.toml index 48ca362..4bb0bc7 100644 --- a/tests/omni_lock_rust/Cargo.toml +++ b/tests/omni_lock_rust/Cargo.toml @@ -8,33 +8,25 @@ edition = "2018" [dependencies] blake2b-rs = "0.1" -ckb-crypto = "0.100.0-rc2" -ckb-error = "0.100.0-rc2" -ckb-hash = "0.100.0-rc2" -ckb-script = "0.100.0-rc2" -ckb-traits = "0.100.0-rc2" -ckb-types = "0.100.0-rc2" -ckb-chain-spec = "0.100.0-rc2" -# ckb-crypto = "0.40.0" -# ckb-error = "0.40.0" -# ckb-hash = "0.40.0" -# ckb-script = "0.40.0" -# ckb-traits = "0.40.0" -# ckb-types = "0.40.0" -# ckb-vm = "=0.19.3" +ckb-crypto = "0.113.0" +ckb-error = "0.113.0" +ckb-hash = "0.113.0" +ckb-script = "0.113.0" +ckb-traits = "0.113.0" +ckb-types = "0.113.0" +ckb-chain-spec = "0.113.0" +ckb-vm = "0.24.6" +ckb-vm-debug-utils = { version = "0.113.0", features = ["stdio"]} + lazy_static = "1.3.0" rand = "0.6.5" sparse-merkle-tree = { git = "https://github.com/nervosnetwork/sparse-merkle-tree.git", rev = "2dce546"} openssl = "0.10.4" sha3 = "0.9.1" -ckb-vm-debug-utils = { git = "https://github.com/nervosnetwork/ckb-vm-debug-utils.git", rev = "f72995f" } gdb-remote-protocol = { git = "https://github.com/luser/rust-gdb-remote-protocol", rev = "565ab0c" } -ckb-vm = { version = "=0.20.0-rc2", features = ["detect-asm"] } ripemd = "0.1.3" sha2 = "0.10.6" hex = "0.4.3" - -[build-dependencies] -includedir_codegen = "0.5.0" -blake2b-rs = "0.1.5" -faster-hex = "0.3" +faster-hex = "0.9.0" +molecule = "0.7.5" +blake2b-ref = "0.3.1" diff --git a/tests/omni_lock_rust/rust-toolchain b/tests/omni_lock_rust/rust-toolchain index 4934985..883bde3 100644 --- a/tests/omni_lock_rust/rust-toolchain +++ b/tests/omni_lock_rust/rust-toolchain @@ -1 +1 @@ -1.69.0 +1.71.1 \ No newline at end of file diff --git a/tests/omni_lock_rust/src/blake2b.rs b/tests/omni_lock_rust/src/blake2b.rs new file mode 100644 index 0000000..fcdf506 --- /dev/null +++ b/tests/omni_lock_rust/src/blake2b.rs @@ -0,0 +1,26 @@ +pub use blake2b_ref::{Blake2b, Blake2bBuilder}; + +pub const PERSONALIZATION_SIGHASH_ALL: &[u8] = b"ckb-tcob-sighash"; +pub const PERSONALIZATION_SIGHASH_ALL_ONLY: &[u8] = b"ckb-tcob-sgohash"; +pub const PERSONALIZATION_OTX: &[u8] = b"ckb-tcob-otxhash"; + +/// return a blake2b instance with personalization for SighashAll +pub fn new_sighash_all_blake2b() -> Blake2b { + Blake2bBuilder::new(32) + .personal(PERSONALIZATION_SIGHASH_ALL) + .build() +} + +/// return a blake2b instance with personalization for SighashAllOnly +pub fn new_sighash_all_only_blake2b() -> Blake2b { + Blake2bBuilder::new(32) + .personal(PERSONALIZATION_SIGHASH_ALL_ONLY) + .build() +} + +/// return a blake2b instance with personalization for OTX +pub fn new_otx_blake2b() -> Blake2b { + Blake2bBuilder::new(32) + .personal(PERSONALIZATION_OTX) + .build() +} diff --git a/tests/omni_lock_rust/src/debug_utils.rs b/tests/omni_lock_rust/src/debug_utils.rs index 67844e3..f8ddd49 100644 --- a/tests/omni_lock_rust/src/debug_utils.rs +++ b/tests/omni_lock_rust/src/debug_utils.rs @@ -1,75 +1,83 @@ -#![allow(unused_imports)] -#![allow(dead_code)] +// #![allow(unused_imports)] +// #![allow(dead_code)] -use ckb_script::cost_model::transferred_byte_cycles; -use ckb_script::{ScriptGroup, ScriptGroupType, ScriptVersion, TransactionScriptsVerifier}; -use ckb_traits::{CellDataProvider, HeaderProvider}; -use ckb_types::bytes::Bytes; -use ckb_types::packed::Byte32; -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; -use ckb_vm::{DefaultMachineBuilder, SupportMachine}; -use ckb_vm_debug_utils::{GdbHandler, Stdio}; -use gdb_remote_protocol::process_packets_from; -use std::net::TcpListener; +// use ckb_script::cost_model::transferred_byte_cycles; +// use ckb_script::{ScriptGroup, ScriptGroupType, ScriptVersion, TransactionScriptsVerifier}; +// use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; +// use ckb_types::bytes::Bytes; +// use ckb_types::packed::Byte32; +// use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +// use ckb_vm::{DefaultMachineBuilder, SupportMachine}; +// use ckb_vm_debug_utils::{GdbHandler, Stdio}; +// use gdb_remote_protocol::process_packets_from; +// use std::net::TcpListener; -/* -* addr: the address listening on, e.g. 127.0.0.1:9999 -* script_group: the script_group (type/lock) to run -* program: bytes of risc-v binary which must contain debug information -* args: arguments passed to script -* verifier: -*/ -pub fn debug<'a, DL: CellDataProvider + HeaderProvider>( - addr: &str, - script_type: ScriptGroupType, - script_hash: Byte32, - program: &Bytes, - args: &[Bytes], - verifier: &TransactionScriptsVerifier<'a, DL>, -) { - let script_group = get_script_group(&verifier, script_type, &script_hash).unwrap(); +// /* +// * addr: the address listening on, e.g. 127.0.0.1:9999 +// * script_group: the script_group (type/lock) to run +// * program: bytes of risc-v binary which must contain debug information +// * args: arguments passed to script +// * verifier: +// */ +// pub fn debug< +// 'a, +// DL: CellDataProvider + ExtensionProvider + HeaderProvider + Send + Sync + Clone, +// >( +// addr: &str, +// script_type: ScriptGroupType, +// script_hash: Byte32, +// program: &Bytes, +// args: &[Bytes], +// verifier: &TransactionScriptsVerifier
, +// ) { +// let script_group = get_script_group(&verifier, script_type, &script_hash).unwrap(); - // GDB path - let listener = TcpListener::bind(addr).expect("listen"); - let script_version = ScriptVersion::V1; - let max_cycle = 70_000_000u64; +// // GDB path +// let listener = TcpListener::bind(addr).expect("listen"); +// let script_version = ScriptVersion::V1; +// let max_cycle = 70_000_000u64; - for res in listener.incoming() { - if let Ok(stream) = res { - let core_machine = AsmCoreMachine::new( - script_version.vm_isa(), - script_version.vm_version(), - max_cycle, - ); - let builder = DefaultMachineBuilder::new(core_machine) - .instruction_cycle_func(verifier.cost_model()) - .syscall(Box::new(Stdio::new(true))); - let builder = verifier - .generate_syscalls(script_version, script_group) - .into_iter() - .fold(builder, |builder, syscall| builder.syscall(syscall)); - let mut machine = AsmMachine::new(builder.build(), None); - let bytes = machine.load_program(&program, args).expect("load program"); - machine - .machine - .add_cycles(transferred_byte_cycles(bytes)) - .expect("load program cycles"); - machine.machine.set_running(true); - let h = GdbHandler::new(machine); - process_packets_from(stream.try_clone().unwrap(), stream, h); - } - } -} +// for res in listener.incoming() { +// if let Ok(stream) = res { +// let core_machine = AsmCoreMachine::new( +// script_version.vm_isa(), +// script_version.vm_version(), +// max_cycle, +// ); +// let builder = DefaultMachineBuilder::new(core_machine) +// .instruction_cycle_func(Box::new(ckb_vm::cost_model::estimate_cycles)) +// .syscall(Box::new(Stdio::new(true))); -fn get_script_group<'a, DL: CellDataProvider + HeaderProvider>( - verifier: &'a TransactionScriptsVerifier<'a, DL>, - group_type: ScriptGroupType, - hash: &Byte32, -) -> Option<&'a ScriptGroup> { - for (t, h, g) in verifier.groups() { - if group_type == t && h == hash { - return Some(g); - } - } - None -} +// let builder = verifier +// .generate_syscalls(script_version, script_group, Default::default()) +// .into_iter() +// .fold(builder, |builder, syscall| builder.syscall(syscall)); +// let mut machine = AsmMachine::new(builder.build()); +// let bytes = machine.load_program(&program, args).expect("load program"); +// machine +// .machine +// .add_cycles(transferred_byte_cycles(bytes)) +// .expect("load program cycles"); +// machine.machine.set_running(true); + +// let h = GdbHandler::new(machine); +// process_packets_from(stream.try_clone().unwrap(), stream, h); +// } +// } +// } + +// fn get_script_group< +// 'a, +// DL: CellDataProvider + ExtensionProvider + HeaderProvider + Send + Sync + Clone, +// >( +// verifier: &'a TransactionScriptsVerifier
, +// group_type: ScriptGroupType, +// hash: &Byte32, +// ) -> Option<&'a ScriptGroup> { +// for (h, g) in verifier.groups() { +// if group_type == g.group_type && h == hash { +// return Some(g); +// } +// } +// None +// } diff --git a/tests/omni_lock_rust/src/lib.rs b/tests/omni_lock_rust/src/lib.rs index 3e548dc..6d0acce 100644 --- a/tests/omni_lock_rust/src/lib.rs +++ b/tests/omni_lock_rust/src/lib.rs @@ -1,3 +1,5 @@ +pub mod blake2b; pub mod debug_utils; pub mod omni_lock; +pub mod schemas; pub mod xudt_rce_mol; diff --git a/tests/omni_lock_rust/src/schemas/basic.rs b/tests/omni_lock_rust/src/schemas/basic.rs new file mode 100644 index 0000000..117b595 --- /dev/null +++ b/tests/omni_lock_rust/src/schemas/basic.rs @@ -0,0 +1,5200 @@ +// Generated by Molecule 0.7.5 + +use super::blockchain::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct Hash(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Hash { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Hash { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Hash { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for Hash { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Hash::new_unchecked(v) + } +} +impl Hash { + const DEFAULT_VALUE: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]; + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn nth0(&self) -> Byte { + Byte::new_unchecked(self.0.slice(0..1)) + } + pub fn nth1(&self) -> Byte { + Byte::new_unchecked(self.0.slice(1..2)) + } + pub fn nth2(&self) -> Byte { + Byte::new_unchecked(self.0.slice(2..3)) + } + pub fn nth3(&self) -> Byte { + Byte::new_unchecked(self.0.slice(3..4)) + } + pub fn nth4(&self) -> Byte { + Byte::new_unchecked(self.0.slice(4..5)) + } + pub fn nth5(&self) -> Byte { + Byte::new_unchecked(self.0.slice(5..6)) + } + pub fn nth6(&self) -> Byte { + Byte::new_unchecked(self.0.slice(6..7)) + } + pub fn nth7(&self) -> Byte { + Byte::new_unchecked(self.0.slice(7..8)) + } + pub fn nth8(&self) -> Byte { + Byte::new_unchecked(self.0.slice(8..9)) + } + pub fn nth9(&self) -> Byte { + Byte::new_unchecked(self.0.slice(9..10)) + } + pub fn nth10(&self) -> Byte { + Byte::new_unchecked(self.0.slice(10..11)) + } + pub fn nth11(&self) -> Byte { + Byte::new_unchecked(self.0.slice(11..12)) + } + pub fn nth12(&self) -> Byte { + Byte::new_unchecked(self.0.slice(12..13)) + } + pub fn nth13(&self) -> Byte { + Byte::new_unchecked(self.0.slice(13..14)) + } + pub fn nth14(&self) -> Byte { + Byte::new_unchecked(self.0.slice(14..15)) + } + pub fn nth15(&self) -> Byte { + Byte::new_unchecked(self.0.slice(15..16)) + } + pub fn nth16(&self) -> Byte { + Byte::new_unchecked(self.0.slice(16..17)) + } + pub fn nth17(&self) -> Byte { + Byte::new_unchecked(self.0.slice(17..18)) + } + pub fn nth18(&self) -> Byte { + Byte::new_unchecked(self.0.slice(18..19)) + } + pub fn nth19(&self) -> Byte { + Byte::new_unchecked(self.0.slice(19..20)) + } + pub fn nth20(&self) -> Byte { + Byte::new_unchecked(self.0.slice(20..21)) + } + pub fn nth21(&self) -> Byte { + Byte::new_unchecked(self.0.slice(21..22)) + } + pub fn nth22(&self) -> Byte { + Byte::new_unchecked(self.0.slice(22..23)) + } + pub fn nth23(&self) -> Byte { + Byte::new_unchecked(self.0.slice(23..24)) + } + pub fn nth24(&self) -> Byte { + Byte::new_unchecked(self.0.slice(24..25)) + } + pub fn nth25(&self) -> Byte { + Byte::new_unchecked(self.0.slice(25..26)) + } + pub fn nth26(&self) -> Byte { + Byte::new_unchecked(self.0.slice(26..27)) + } + pub fn nth27(&self) -> Byte { + Byte::new_unchecked(self.0.slice(27..28)) + } + pub fn nth28(&self) -> Byte { + Byte::new_unchecked(self.0.slice(28..29)) + } + pub fn nth29(&self) -> Byte { + Byte::new_unchecked(self.0.slice(29..30)) + } + pub fn nth30(&self) -> Byte { + Byte::new_unchecked(self.0.slice(30..31)) + } + pub fn nth31(&self) -> Byte { + Byte::new_unchecked(self.0.slice(31..32)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.as_bytes() + } + pub fn as_reader<'r>(&'r self) -> HashReader<'r> { + HashReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Hash { + type Builder = HashBuilder; + const NAME: &'static str = "Hash"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Hash(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + HashReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + HashReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set([ + self.nth0(), + self.nth1(), + self.nth2(), + self.nth3(), + self.nth4(), + self.nth5(), + self.nth6(), + self.nth7(), + self.nth8(), + self.nth9(), + self.nth10(), + self.nth11(), + self.nth12(), + self.nth13(), + self.nth14(), + self.nth15(), + self.nth16(), + self.nth17(), + self.nth18(), + self.nth19(), + self.nth20(), + self.nth21(), + self.nth22(), + self.nth23(), + self.nth24(), + self.nth25(), + self.nth26(), + self.nth27(), + self.nth28(), + self.nth29(), + self.nth30(), + self.nth31(), + ]) + } +} +#[derive(Clone, Copy)] +pub struct HashReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for HashReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for HashReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for HashReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> HashReader<'r> { + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn nth0(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[0..1]) + } + pub fn nth1(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[1..2]) + } + pub fn nth2(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[2..3]) + } + pub fn nth3(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[3..4]) + } + pub fn nth4(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[4..5]) + } + pub fn nth5(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[5..6]) + } + pub fn nth6(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[6..7]) + } + pub fn nth7(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[7..8]) + } + pub fn nth8(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[8..9]) + } + pub fn nth9(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[9..10]) + } + pub fn nth10(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[10..11]) + } + pub fn nth11(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[11..12]) + } + pub fn nth12(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[12..13]) + } + pub fn nth13(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[13..14]) + } + pub fn nth14(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[14..15]) + } + pub fn nth15(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[15..16]) + } + pub fn nth16(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[16..17]) + } + pub fn nth17(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[17..18]) + } + pub fn nth18(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[18..19]) + } + pub fn nth19(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[19..20]) + } + pub fn nth20(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[20..21]) + } + pub fn nth21(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[21..22]) + } + pub fn nth22(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[22..23]) + } + pub fn nth23(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[23..24]) + } + pub fn nth24(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[24..25]) + } + pub fn nth25(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[25..26]) + } + pub fn nth26(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[26..27]) + } + pub fn nth27(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[27..28]) + } + pub fn nth28(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[28..29]) + } + pub fn nth29(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[29..30]) + } + pub fn nth30(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[30..31]) + } + pub fn nth31(&self) -> ByteReader<'r> { + ByteReader::new_unchecked(&self.as_slice()[31..32]) + } + pub fn raw_data(&self) -> &'r [u8] { + self.as_slice() + } +} +impl<'r> molecule::prelude::Reader<'r> for HashReader<'r> { + type Entity = Hash; + const NAME: &'static str = "HashReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + HashReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len != Self::TOTAL_SIZE { + return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); + } + Ok(()) + } +} +pub struct HashBuilder(pub(crate) [Byte; 32]); +impl ::core::fmt::Debug for HashBuilder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:?})", Self::NAME, &self.0[..]) + } +} +impl ::core::default::Default for HashBuilder { + fn default() -> Self { + HashBuilder([ + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + Byte::default(), + ]) + } +} +impl HashBuilder { + pub const TOTAL_SIZE: usize = 32; + pub const ITEM_SIZE: usize = 1; + pub const ITEM_COUNT: usize = 32; + pub fn set(mut self, v: [Byte; 32]) -> Self { + self.0 = v; + self + } + pub fn nth0(mut self, v: Byte) -> Self { + self.0[0] = v; + self + } + pub fn nth1(mut self, v: Byte) -> Self { + self.0[1] = v; + self + } + pub fn nth2(mut self, v: Byte) -> Self { + self.0[2] = v; + self + } + pub fn nth3(mut self, v: Byte) -> Self { + self.0[3] = v; + self + } + pub fn nth4(mut self, v: Byte) -> Self { + self.0[4] = v; + self + } + pub fn nth5(mut self, v: Byte) -> Self { + self.0[5] = v; + self + } + pub fn nth6(mut self, v: Byte) -> Self { + self.0[6] = v; + self + } + pub fn nth7(mut self, v: Byte) -> Self { + self.0[7] = v; + self + } + pub fn nth8(mut self, v: Byte) -> Self { + self.0[8] = v; + self + } + pub fn nth9(mut self, v: Byte) -> Self { + self.0[9] = v; + self + } + pub fn nth10(mut self, v: Byte) -> Self { + self.0[10] = v; + self + } + pub fn nth11(mut self, v: Byte) -> Self { + self.0[11] = v; + self + } + pub fn nth12(mut self, v: Byte) -> Self { + self.0[12] = v; + self + } + pub fn nth13(mut self, v: Byte) -> Self { + self.0[13] = v; + self + } + pub fn nth14(mut self, v: Byte) -> Self { + self.0[14] = v; + self + } + pub fn nth15(mut self, v: Byte) -> Self { + self.0[15] = v; + self + } + pub fn nth16(mut self, v: Byte) -> Self { + self.0[16] = v; + self + } + pub fn nth17(mut self, v: Byte) -> Self { + self.0[17] = v; + self + } + pub fn nth18(mut self, v: Byte) -> Self { + self.0[18] = v; + self + } + pub fn nth19(mut self, v: Byte) -> Self { + self.0[19] = v; + self + } + pub fn nth20(mut self, v: Byte) -> Self { + self.0[20] = v; + self + } + pub fn nth21(mut self, v: Byte) -> Self { + self.0[21] = v; + self + } + pub fn nth22(mut self, v: Byte) -> Self { + self.0[22] = v; + self + } + pub fn nth23(mut self, v: Byte) -> Self { + self.0[23] = v; + self + } + pub fn nth24(mut self, v: Byte) -> Self { + self.0[24] = v; + self + } + pub fn nth25(mut self, v: Byte) -> Self { + self.0[25] = v; + self + } + pub fn nth26(mut self, v: Byte) -> Self { + self.0[26] = v; + self + } + pub fn nth27(mut self, v: Byte) -> Self { + self.0[27] = v; + self + } + pub fn nth28(mut self, v: Byte) -> Self { + self.0[28] = v; + self + } + pub fn nth29(mut self, v: Byte) -> Self { + self.0[29] = v; + self + } + pub fn nth30(mut self, v: Byte) -> Self { + self.0[30] = v; + self + } + pub fn nth31(mut self, v: Byte) -> Self { + self.0[31] = v; + self + } +} +impl molecule::prelude::Builder for HashBuilder { + type Entity = Hash; + const NAME: &'static str = "HashBuilder"; + fn expected_length(&self) -> usize { + Self::TOTAL_SIZE + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(self.0[0].as_slice())?; + writer.write_all(self.0[1].as_slice())?; + writer.write_all(self.0[2].as_slice())?; + writer.write_all(self.0[3].as_slice())?; + writer.write_all(self.0[4].as_slice())?; + writer.write_all(self.0[5].as_slice())?; + writer.write_all(self.0[6].as_slice())?; + writer.write_all(self.0[7].as_slice())?; + writer.write_all(self.0[8].as_slice())?; + writer.write_all(self.0[9].as_slice())?; + writer.write_all(self.0[10].as_slice())?; + writer.write_all(self.0[11].as_slice())?; + writer.write_all(self.0[12].as_slice())?; + writer.write_all(self.0[13].as_slice())?; + writer.write_all(self.0[14].as_slice())?; + writer.write_all(self.0[15].as_slice())?; + writer.write_all(self.0[16].as_slice())?; + writer.write_all(self.0[17].as_slice())?; + writer.write_all(self.0[18].as_slice())?; + writer.write_all(self.0[19].as_slice())?; + writer.write_all(self.0[20].as_slice())?; + writer.write_all(self.0[21].as_slice())?; + writer.write_all(self.0[22].as_slice())?; + writer.write_all(self.0[23].as_slice())?; + writer.write_all(self.0[24].as_slice())?; + writer.write_all(self.0[25].as_slice())?; + writer.write_all(self.0[26].as_slice())?; + writer.write_all(self.0[27].as_slice())?; + writer.write_all(self.0[28].as_slice())?; + writer.write_all(self.0[29].as_slice())?; + writer.write_all(self.0[30].as_slice())?; + writer.write_all(self.0[31].as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Hash::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct String(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for String { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for String { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for String { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl ::core::default::Default for String { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + String::new_unchecked(v) + } +} +impl String { + const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Byte { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + Byte::new_unchecked(self.0.slice(start..end)) + } + pub fn raw_data(&self) -> molecule::bytes::Bytes { + self.0.slice(molecule::NUMBER_SIZE..) + } + pub fn as_reader<'r>(&'r self) -> StringReader<'r> { + StringReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for String { + type Builder = StringBuilder; + const NAME: &'static str = "String"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + String(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + StringReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + StringReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct StringReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for StringReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for StringReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for StringReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + let raw_data = hex_string(&self.raw_data()); + write!(f, "{}(0x{})", Self::NAME, raw_data) + } +} +impl<'r> StringReader<'r> { + pub const ITEM_SIZE: usize = 1; + pub fn total_size(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() + } + pub fn item_count(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { + let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; + let end = start + Self::ITEM_SIZE; + ByteReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn raw_data(&self) -> &'r [u8] { + &self.as_slice()[molecule::NUMBER_SIZE..] + } +} +impl<'r> molecule::prelude::Reader<'r> for StringReader<'r> { + type Entity = String; + const NAME: &'static str = "StringReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + StringReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_count = molecule::unpack_number(slice) as usize; + if item_count == 0 { + if slice_len != molecule::NUMBER_SIZE { + return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); + } + return Ok(()); + } + let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct StringBuilder(pub(crate) Vec); +impl StringBuilder { + pub const ITEM_SIZE: usize = 1; + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Byte) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Byte) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for StringBuilder { + type Entity = String; + const NAME: &'static str = "StringBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; + for inner in &self.0[..] { + writer.write_all(inner.as_slice())?; + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + String::new_unchecked(inner.into()) + } +} +pub struct StringIterator(String, usize, usize); +impl ::core::iter::Iterator for StringIterator { + type Item = Byte; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for StringIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for String { + type Item = Byte; + type IntoIter = StringIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + StringIterator(self, 0, len) + } +} +#[derive(Clone)] +pub struct Uint32Opt(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Uint32Opt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Uint32Opt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Uint32Opt { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl ::core::default::Default for Uint32Opt { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Uint32Opt::new_unchecked(v) + } +} +impl Uint32Opt { + const DEFAULT_VALUE: [u8; 0] = []; + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option { + if self.is_none() { + None + } else { + Some(Uint32::new_unchecked(self.0.clone())) + } + } + pub fn as_reader<'r>(&'r self) -> Uint32OptReader<'r> { + Uint32OptReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Uint32Opt { + type Builder = Uint32OptBuilder; + const NAME: &'static str = "Uint32Opt"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Uint32Opt(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32OptReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + Uint32OptReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_opt()) + } +} +#[derive(Clone, Copy)] +pub struct Uint32OptReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for Uint32OptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for Uint32OptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for Uint32OptReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(v) = self.to_opt() { + write!(f, "{}(Some({}))", Self::NAME, v) + } else { + write!(f, "{}(None)", Self::NAME) + } + } +} +impl<'r> Uint32OptReader<'r> { + pub fn is_none(&self) -> bool { + self.0.is_empty() + } + pub fn is_some(&self) -> bool { + !self.0.is_empty() + } + pub fn to_opt(&self) -> Option> { + if self.is_none() { + None + } else { + Some(Uint32Reader::new_unchecked(self.as_slice())) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for Uint32OptReader<'r> { + type Entity = Uint32Opt; + const NAME: &'static str = "Uint32OptReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + Uint32OptReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + if !slice.is_empty() { + Uint32Reader::verify(&slice[..], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct Uint32OptBuilder(pub(crate) Option); +impl Uint32OptBuilder { + pub fn set(mut self, v: Option) -> Self { + self.0 = v; + self + } +} +impl molecule::prelude::Builder for Uint32OptBuilder { + type Entity = Uint32Opt; + const NAME: &'static str = "Uint32OptBuilder"; + fn expected_length(&self) -> usize { + self.0 + .as_ref() + .map(|ref inner| inner.as_slice().len()) + .unwrap_or(0) + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + self.0 + .as_ref() + .map(|ref inner| writer.write_all(inner.as_slice())) + .unwrap_or(Ok(())) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Uint32Opt::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Action(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Action { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Action { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Action { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "script_info_hash", self.script_info_hash())?; + write!(f, ", {}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "data", self.data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Action { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Action::new_unchecked(v) + } +} +impl Action { + const DEFAULT_VALUE: [u8; 84] = [ + 84, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn script_info_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn script_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn data(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ActionReader<'r> { + ActionReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Action { + type Builder = ActionBuilder; + const NAME: &'static str = "Action"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Action(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ActionReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ActionReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .script_info_hash(self.script_info_hash()) + .script_hash(self.script_hash()) + .data(self.data()) + } +} +#[derive(Clone, Copy)] +pub struct ActionReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ActionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ActionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ActionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "script_info_hash", self.script_info_hash())?; + write!(f, ", {}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "data", self.data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ActionReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn script_info_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn script_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn data(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ActionReader<'r> { + type Entity = Action; + const NAME: &'static str = "ActionReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ActionReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Byte32Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + BytesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ActionBuilder { + pub(crate) script_info_hash: Byte32, + pub(crate) script_hash: Byte32, + pub(crate) data: Bytes, +} +impl ActionBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn script_info_hash(mut self, v: Byte32) -> Self { + self.script_info_hash = v; + self + } + pub fn script_hash(mut self, v: Byte32) -> Self { + self.script_hash = v; + self + } + pub fn data(mut self, v: Bytes) -> Self { + self.data = v; + self + } +} +impl molecule::prelude::Builder for ActionBuilder { + type Entity = Action; + const NAME: &'static str = "ActionBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.script_info_hash.as_slice().len() + + self.script_hash.as_slice().len() + + self.data.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.script_info_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.script_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.data.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.script_info_hash.as_slice())?; + writer.write_all(self.script_hash.as_slice())?; + writer.write_all(self.data.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Action::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct ActionVec(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ActionVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ActionVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ActionVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for ActionVec { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ActionVec::new_unchecked(v) + } +} +impl ActionVec { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> Action { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + Action::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + Action::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> ActionVecReader<'r> { + ActionVecReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ActionVec { + type Builder = ActionVecBuilder; + const NAME: &'static str = "ActionVec"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ActionVec(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ActionVecReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ActionVecReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct ActionVecReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ActionVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ActionVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ActionVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> ActionVecReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ActionReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + ActionReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + ActionReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ActionVecReader<'r> { + type Entity = ActionVec; + const NAME: &'static str = "ActionVecReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ActionVecReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + ActionReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ActionVecBuilder(pub(crate) Vec); +impl ActionVecBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: Action) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: Action) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for ActionVecBuilder { + type Entity = ActionVec; + const NAME: &'static str = "ActionVecBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ActionVec::new_unchecked(inner.into()) + } +} +pub struct ActionVecIterator(ActionVec, usize, usize); +impl ::core::iter::Iterator for ActionVecIterator { + type Item = Action; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for ActionVecIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for ActionVec { + type Item = Action; + type IntoIter = ActionVecIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + ActionVecIterator(self, 0, len) + } +} +impl<'r> ActionVecReader<'r> { + pub fn iter<'t>(&'t self) -> ActionVecReaderIterator<'t, 'r> { + ActionVecReaderIterator(&self, 0, self.len()) + } +} +pub struct ActionVecReaderIterator<'t, 'r>(&'t ActionVecReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for ActionVecReaderIterator<'t, 'r> { + type Item = ActionReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for ActionVecReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct Message(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Message { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Message { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Message { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "actions", self.actions())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Message { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Message::new_unchecked(v) + } +} +impl Message { + const DEFAULT_VALUE: [u8; 12] = [12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0]; + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn actions(&self) -> ActionVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + ActionVec::new_unchecked(self.0.slice(start..end)) + } else { + ActionVec::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> MessageReader<'r> { + MessageReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Message { + type Builder = MessageBuilder; + const NAME: &'static str = "Message"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Message(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MessageReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + MessageReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().actions(self.actions()) + } +} +#[derive(Clone, Copy)] +pub struct MessageReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for MessageReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for MessageReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for MessageReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "actions", self.actions())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> MessageReader<'r> { + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn actions(&self) -> ActionVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + ActionVecReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ActionVecReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for MessageReader<'r> { + type Entity = Message; + const NAME: &'static str = "MessageReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + MessageReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + ActionVecReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct MessageBuilder { + pub(crate) actions: ActionVec, +} +impl MessageBuilder { + pub const FIELD_COUNT: usize = 1; + pub fn actions(mut self, v: ActionVec) -> Self { + self.actions = v; + self + } +} +impl molecule::prelude::Builder for MessageBuilder { + type Entity = Message; + const NAME: &'static str = "MessageBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.actions.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.actions.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.actions.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Message::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct ScriptInfo(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ScriptInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ScriptInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ScriptInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "name", self.name())?; + write!(f, ", {}: {}", "url", self.url())?; + write!(f, ", {}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "schema", self.schema())?; + write!(f, ", {}: {}", "message_type", self.message_type())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ScriptInfo { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ScriptInfo::new_unchecked(v) + } +} +impl ScriptInfo { + const DEFAULT_VALUE: [u8; 72] = [ + 72, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 64, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 5; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn name(&self) -> String { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + String::new_unchecked(self.0.slice(start..end)) + } + pub fn url(&self) -> String { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + String::new_unchecked(self.0.slice(start..end)) + } + pub fn script_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn schema(&self) -> String { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + String::new_unchecked(self.0.slice(start..end)) + } + pub fn message_type(&self) -> String { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[24..]) as usize; + String::new_unchecked(self.0.slice(start..end)) + } else { + String::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ScriptInfoReader<'r> { + ScriptInfoReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ScriptInfo { + type Builder = ScriptInfoBuilder; + const NAME: &'static str = "ScriptInfo"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ScriptInfo(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ScriptInfoReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ScriptInfoReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .name(self.name()) + .url(self.url()) + .script_hash(self.script_hash()) + .schema(self.schema()) + .message_type(self.message_type()) + } +} +#[derive(Clone, Copy)] +pub struct ScriptInfoReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ScriptInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ScriptInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ScriptInfoReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "name", self.name())?; + write!(f, ", {}: {}", "url", self.url())?; + write!(f, ", {}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "schema", self.schema())?; + write!(f, ", {}: {}", "message_type", self.message_type())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ScriptInfoReader<'r> { + pub const FIELD_COUNT: usize = 5; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn name(&self) -> StringReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + StringReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn url(&self) -> StringReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + StringReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn script_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn schema(&self) -> StringReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + StringReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn message_type(&self) -> StringReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[24..]) as usize; + StringReader::new_unchecked(&self.as_slice()[start..end]) + } else { + StringReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ScriptInfoReader<'r> { + type Entity = ScriptInfo; + const NAME: &'static str = "ScriptInfoReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ScriptInfoReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + StringReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + StringReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Byte32Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + StringReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + StringReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ScriptInfoBuilder { + pub(crate) name: String, + pub(crate) url: String, + pub(crate) script_hash: Byte32, + pub(crate) schema: String, + pub(crate) message_type: String, +} +impl ScriptInfoBuilder { + pub const FIELD_COUNT: usize = 5; + pub fn name(mut self, v: String) -> Self { + self.name = v; + self + } + pub fn url(mut self, v: String) -> Self { + self.url = v; + self + } + pub fn script_hash(mut self, v: Byte32) -> Self { + self.script_hash = v; + self + } + pub fn schema(mut self, v: String) -> Self { + self.schema = v; + self + } + pub fn message_type(mut self, v: String) -> Self { + self.message_type = v; + self + } +} +impl molecule::prelude::Builder for ScriptInfoBuilder { + type Entity = ScriptInfo; + const NAME: &'static str = "ScriptInfoBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.name.as_slice().len() + + self.url.as_slice().len() + + self.script_hash.as_slice().len() + + self.schema.as_slice().len() + + self.message_type.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.name.as_slice().len(); + offsets.push(total_size); + total_size += self.url.as_slice().len(); + offsets.push(total_size); + total_size += self.script_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.schema.as_slice().len(); + offsets.push(total_size); + total_size += self.message_type.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.name.as_slice())?; + writer.write_all(self.url.as_slice())?; + writer.write_all(self.script_hash.as_slice())?; + writer.write_all(self.schema.as_slice())?; + writer.write_all(self.message_type.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ScriptInfo::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct ScriptInfoVec(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ScriptInfoVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ScriptInfoVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ScriptInfoVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for ScriptInfoVec { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ScriptInfoVec::new_unchecked(v) + } +} +impl ScriptInfoVec { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ScriptInfo { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + ScriptInfo::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + ScriptInfo::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> ScriptInfoVecReader<'r> { + ScriptInfoVecReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ScriptInfoVec { + type Builder = ScriptInfoVecBuilder; + const NAME: &'static str = "ScriptInfoVec"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ScriptInfoVec(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ScriptInfoVecReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ScriptInfoVecReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct ScriptInfoVecReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ScriptInfoVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ScriptInfoVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ScriptInfoVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> ScriptInfoVecReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> ScriptInfoReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + ScriptInfoReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + ScriptInfoReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ScriptInfoVecReader<'r> { + type Entity = ScriptInfoVec; + const NAME: &'static str = "ScriptInfoVecReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ScriptInfoVecReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + ScriptInfoReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ScriptInfoVecBuilder(pub(crate) Vec); +impl ScriptInfoVecBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: ScriptInfo) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: ScriptInfo) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for ScriptInfoVecBuilder { + type Entity = ScriptInfoVec; + const NAME: &'static str = "ScriptInfoVecBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ScriptInfoVec::new_unchecked(inner.into()) + } +} +pub struct ScriptInfoVecIterator(ScriptInfoVec, usize, usize); +impl ::core::iter::Iterator for ScriptInfoVecIterator { + type Item = ScriptInfo; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for ScriptInfoVecIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for ScriptInfoVec { + type Item = ScriptInfo; + type IntoIter = ScriptInfoVecIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + ScriptInfoVecIterator(self, 0, len) + } +} +impl<'r> ScriptInfoVecReader<'r> { + pub fn iter<'t>(&'t self) -> ScriptInfoVecReaderIterator<'t, 'r> { + ScriptInfoVecReaderIterator(&self, 0, self.len()) + } +} +pub struct ScriptInfoVecReaderIterator<'t, 'r>(&'t ScriptInfoVecReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for ScriptInfoVecReaderIterator<'t, 'r> { + type Item = ScriptInfoReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for ScriptInfoVecReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct ResolvedInputs(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ResolvedInputs { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ResolvedInputs { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ResolvedInputs { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "outputs", self.outputs())?; + write!(f, ", {}: {}", "outputs_data", self.outputs_data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ResolvedInputs { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ResolvedInputs::new_unchecked(v) + } +} +impl ResolvedInputs { + const DEFAULT_VALUE: [u8; 20] = [ + 20, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn outputs(&self) -> CellOutputVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + CellOutputVec::new_unchecked(self.0.slice(start..end)) + } + pub fn outputs_data(&self) -> BytesVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesVec::new_unchecked(self.0.slice(start..end)) + } else { + BytesVec::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ResolvedInputsReader<'r> { + ResolvedInputsReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ResolvedInputs { + type Builder = ResolvedInputsBuilder; + const NAME: &'static str = "ResolvedInputs"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ResolvedInputs(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ResolvedInputsReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ResolvedInputsReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .outputs(self.outputs()) + .outputs_data(self.outputs_data()) + } +} +#[derive(Clone, Copy)] +pub struct ResolvedInputsReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ResolvedInputsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ResolvedInputsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ResolvedInputsReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "outputs", self.outputs())?; + write!(f, ", {}: {}", "outputs_data", self.outputs_data())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ResolvedInputsReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn outputs(&self) -> CellOutputVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + CellOutputVecReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn outputs_data(&self) -> BytesVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesVecReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesVecReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ResolvedInputsReader<'r> { + type Entity = ResolvedInputs; + const NAME: &'static str = "ResolvedInputsReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ResolvedInputsReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + CellOutputVecReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesVecReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct ResolvedInputsBuilder { + pub(crate) outputs: CellOutputVec, + pub(crate) outputs_data: BytesVec, +} +impl ResolvedInputsBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn outputs(mut self, v: CellOutputVec) -> Self { + self.outputs = v; + self + } + pub fn outputs_data(mut self, v: BytesVec) -> Self { + self.outputs_data = v; + self + } +} +impl molecule::prelude::Builder for ResolvedInputsBuilder { + type Entity = ResolvedInputs; + const NAME: &'static str = "ResolvedInputsBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.outputs.as_slice().len() + + self.outputs_data.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.outputs.as_slice().len(); + offsets.push(total_size); + total_size += self.outputs_data.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.outputs.as_slice())?; + writer.write_all(self.outputs_data.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ResolvedInputs::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BuildingPacketV1(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BuildingPacketV1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BuildingPacketV1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BuildingPacketV1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "message", self.message())?; + write!(f, ", {}: {}", "payload", self.payload())?; + write!(f, ", {}: {}", "resolved_inputs", self.resolved_inputs())?; + write!(f, ", {}: {}", "change_output", self.change_output())?; + write!(f, ", {}: {}", "script_infos", self.script_infos())?; + write!(f, ", {}: {}", "lock_actions", self.lock_actions())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for BuildingPacketV1 { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + BuildingPacketV1::new_unchecked(v) + } +} +impl BuildingPacketV1 { + const DEFAULT_VALUE: [u8; 136] = [ + 136, 0, 0, 0, 28, 0, 0, 0, 40, 0, 0, 0, 108, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 132, 0, + 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 68, 0, 0, 0, 12, 0, 0, 0, 64, 0, 0, 0, 52, 0, 0, + 0, 28, 0, 0, 0, 32, 0, 0, 0, 36, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 12, + 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 6; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn message(&self) -> Message { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Message::new_unchecked(self.0.slice(start..end)) + } + pub fn payload(&self) -> Transaction { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Transaction::new_unchecked(self.0.slice(start..end)) + } + pub fn resolved_inputs(&self) -> ResolvedInputs { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + ResolvedInputs::new_unchecked(self.0.slice(start..end)) + } + pub fn change_output(&self) -> Uint32Opt { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32Opt::new_unchecked(self.0.slice(start..end)) + } + pub fn script_infos(&self) -> ScriptInfoVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + ScriptInfoVec::new_unchecked(self.0.slice(start..end)) + } + pub fn lock_actions(&self) -> ActionVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[28..]) as usize; + ActionVec::new_unchecked(self.0.slice(start..end)) + } else { + ActionVec::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> BuildingPacketV1Reader<'r> { + BuildingPacketV1Reader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BuildingPacketV1 { + type Builder = BuildingPacketV1Builder; + const NAME: &'static str = "BuildingPacketV1"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BuildingPacketV1(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BuildingPacketV1Reader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BuildingPacketV1Reader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .message(self.message()) + .payload(self.payload()) + .resolved_inputs(self.resolved_inputs()) + .change_output(self.change_output()) + .script_infos(self.script_infos()) + .lock_actions(self.lock_actions()) + } +} +#[derive(Clone, Copy)] +pub struct BuildingPacketV1Reader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BuildingPacketV1Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BuildingPacketV1Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BuildingPacketV1Reader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "message", self.message())?; + write!(f, ", {}: {}", "payload", self.payload())?; + write!(f, ", {}: {}", "resolved_inputs", self.resolved_inputs())?; + write!(f, ", {}: {}", "change_output", self.change_output())?; + write!(f, ", {}: {}", "script_infos", self.script_infos())?; + write!(f, ", {}: {}", "lock_actions", self.lock_actions())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> BuildingPacketV1Reader<'r> { + pub const FIELD_COUNT: usize = 6; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn message(&self) -> MessageReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + MessageReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn payload(&self) -> TransactionReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + TransactionReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn resolved_inputs(&self) -> ResolvedInputsReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + ResolvedInputsReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn change_output(&self) -> Uint32OptReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32OptReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn script_infos(&self) -> ScriptInfoVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + ScriptInfoVecReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn lock_actions(&self) -> ActionVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[28..]) as usize; + ActionVecReader::new_unchecked(&self.as_slice()[start..end]) + } else { + ActionVecReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BuildingPacketV1Reader<'r> { + type Entity = BuildingPacketV1; + const NAME: &'static str = "BuildingPacketV1Reader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BuildingPacketV1Reader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + MessageReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + TransactionReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + ResolvedInputsReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Uint32OptReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + ScriptInfoVecReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + ActionVecReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BuildingPacketV1Builder { + pub(crate) message: Message, + pub(crate) payload: Transaction, + pub(crate) resolved_inputs: ResolvedInputs, + pub(crate) change_output: Uint32Opt, + pub(crate) script_infos: ScriptInfoVec, + pub(crate) lock_actions: ActionVec, +} +impl BuildingPacketV1Builder { + pub const FIELD_COUNT: usize = 6; + pub fn message(mut self, v: Message) -> Self { + self.message = v; + self + } + pub fn payload(mut self, v: Transaction) -> Self { + self.payload = v; + self + } + pub fn resolved_inputs(mut self, v: ResolvedInputs) -> Self { + self.resolved_inputs = v; + self + } + pub fn change_output(mut self, v: Uint32Opt) -> Self { + self.change_output = v; + self + } + pub fn script_infos(mut self, v: ScriptInfoVec) -> Self { + self.script_infos = v; + self + } + pub fn lock_actions(mut self, v: ActionVec) -> Self { + self.lock_actions = v; + self + } +} +impl molecule::prelude::Builder for BuildingPacketV1Builder { + type Entity = BuildingPacketV1; + const NAME: &'static str = "BuildingPacketV1Builder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.message.as_slice().len() + + self.payload.as_slice().len() + + self.resolved_inputs.as_slice().len() + + self.change_output.as_slice().len() + + self.script_infos.as_slice().len() + + self.lock_actions.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.message.as_slice().len(); + offsets.push(total_size); + total_size += self.payload.as_slice().len(); + offsets.push(total_size); + total_size += self.resolved_inputs.as_slice().len(); + offsets.push(total_size); + total_size += self.change_output.as_slice().len(); + offsets.push(total_size); + total_size += self.script_infos.as_slice().len(); + offsets.push(total_size); + total_size += self.lock_actions.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.message.as_slice())?; + writer.write_all(self.payload.as_slice())?; + writer.write_all(self.resolved_inputs.as_slice())?; + writer.write_all(self.change_output.as_slice())?; + writer.write_all(self.script_infos.as_slice())?; + writer.write_all(self.lock_actions.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BuildingPacketV1::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct BuildingPacket(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for BuildingPacket { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for BuildingPacket { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for BuildingPacket { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl ::core::default::Default for BuildingPacket { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + BuildingPacket::new_unchecked(v) + } +} +impl BuildingPacket { + const DEFAULT_VALUE: [u8; 140] = [ + 0, 0, 0, 0, 136, 0, 0, 0, 28, 0, 0, 0, 40, 0, 0, 0, 108, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, + 0, 132, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 68, 0, 0, 0, 12, 0, 0, 0, 64, 0, 0, + 0, 52, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 36, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 20, + 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + ]; + pub const ITEMS_COUNT: usize = 1; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> BuildingPacketUnion { + let inner = self.0.slice(molecule::NUMBER_SIZE..); + match self.item_id() { + 0 => BuildingPacketV1::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } + pub fn as_reader<'r>(&'r self) -> BuildingPacketReader<'r> { + BuildingPacketReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for BuildingPacket { + type Builder = BuildingPacketBuilder; + const NAME: &'static str = "BuildingPacket"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + BuildingPacket(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BuildingPacketReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + BuildingPacketReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_enum()) + } +} +#[derive(Clone, Copy)] +pub struct BuildingPacketReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for BuildingPacketReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for BuildingPacketReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for BuildingPacketReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl<'r> BuildingPacketReader<'r> { + pub const ITEMS_COUNT: usize = 1; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> BuildingPacketUnionReader<'r> { + let inner = &self.as_slice()[molecule::NUMBER_SIZE..]; + match self.item_id() { + 0 => BuildingPacketV1Reader::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } +} +impl<'r> molecule::prelude::Reader<'r> for BuildingPacketReader<'r> { + type Entity = BuildingPacket; + const NAME: &'static str = "BuildingPacketReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + BuildingPacketReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_id = molecule::unpack_number(slice); + let inner_slice = &slice[molecule::NUMBER_SIZE..]; + match item_id { + 0 => BuildingPacketV1Reader::verify(inner_slice, compatible), + _ => ve!(Self, UnknownItem, Self::ITEMS_COUNT, item_id), + }?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct BuildingPacketBuilder(pub(crate) BuildingPacketUnion); +impl BuildingPacketBuilder { + pub const ITEMS_COUNT: usize = 1; + pub fn set(mut self, v: I) -> Self + where + I: ::core::convert::Into, + { + self.0 = v.into(); + self + } +} +impl molecule::prelude::Builder for BuildingPacketBuilder { + type Entity = BuildingPacket; + const NAME: &'static str = "BuildingPacketBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + self.0.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.item_id()))?; + writer.write_all(self.0.as_slice()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + BuildingPacket::new_unchecked(inner.into()) + } +} +#[derive(Debug, Clone)] +pub enum BuildingPacketUnion { + BuildingPacketV1(BuildingPacketV1), +} +#[derive(Debug, Clone, Copy)] +pub enum BuildingPacketUnionReader<'r> { + BuildingPacketV1(BuildingPacketV1Reader<'r>), +} +impl ::core::default::Default for BuildingPacketUnion { + fn default() -> Self { + BuildingPacketUnion::BuildingPacketV1(::core::default::Default::default()) + } +} +impl ::core::fmt::Display for BuildingPacketUnion { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BuildingPacketUnion::BuildingPacketV1(ref item) => { + write!(f, "{}::{}({})", Self::NAME, BuildingPacketV1::NAME, item) + } + } + } +} +impl<'r> ::core::fmt::Display for BuildingPacketUnionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BuildingPacketUnionReader::BuildingPacketV1(ref item) => { + write!(f, "{}::{}({})", Self::NAME, BuildingPacketV1::NAME, item) + } + } + } +} +impl BuildingPacketUnion { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BuildingPacketUnion::BuildingPacketV1(ref item) => write!(f, "{}", item), + } + } +} +impl<'r> BuildingPacketUnionReader<'r> { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + BuildingPacketUnionReader::BuildingPacketV1(ref item) => write!(f, "{}", item), + } + } +} +impl ::core::convert::From for BuildingPacketUnion { + fn from(item: BuildingPacketV1) -> Self { + BuildingPacketUnion::BuildingPacketV1(item) + } +} +impl<'r> ::core::convert::From> for BuildingPacketUnionReader<'r> { + fn from(item: BuildingPacketV1Reader<'r>) -> Self { + BuildingPacketUnionReader::BuildingPacketV1(item) + } +} +impl BuildingPacketUnion { + pub const NAME: &'static str = "BuildingPacketUnion"; + pub fn as_bytes(&self) -> molecule::bytes::Bytes { + match self { + BuildingPacketUnion::BuildingPacketV1(item) => item.as_bytes(), + } + } + pub fn as_slice(&self) -> &[u8] { + match self { + BuildingPacketUnion::BuildingPacketV1(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + BuildingPacketUnion::BuildingPacketV1(_) => 0, + } + } + pub fn item_name(&self) -> &str { + match self { + BuildingPacketUnion::BuildingPacketV1(_) => "BuildingPacketV1", + } + } + pub fn as_reader<'r>(&'r self) -> BuildingPacketUnionReader<'r> { + match self { + BuildingPacketUnion::BuildingPacketV1(item) => item.as_reader().into(), + } + } +} +impl<'r> BuildingPacketUnionReader<'r> { + pub const NAME: &'r str = "BuildingPacketUnionReader"; + pub fn as_slice(&self) -> &'r [u8] { + match self { + BuildingPacketUnionReader::BuildingPacketV1(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + BuildingPacketUnionReader::BuildingPacketV1(_) => 0, + } + } + pub fn item_name(&self) -> &str { + match self { + BuildingPacketUnionReader::BuildingPacketV1(_) => "BuildingPacketV1", + } + } +} +#[derive(Clone)] +pub struct SighashAll(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for SighashAll { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for SighashAll { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for SighashAll { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "message", self.message())?; + write!(f, ", {}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for SighashAll { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + SighashAll::new_unchecked(v) + } +} +impl SighashAll { + const DEFAULT_VALUE: [u8; 28] = [ + 28, 0, 0, 0, 12, 0, 0, 0, 24, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn message(&self) -> Message { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Message::new_unchecked(self.0.slice(start..end)) + } + pub fn seal(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> SighashAllReader<'r> { + SighashAllReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for SighashAll { + type Builder = SighashAllBuilder; + const NAME: &'static str = "SighashAll"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + SighashAll(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SighashAllReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SighashAllReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .message(self.message()) + .seal(self.seal()) + } +} +#[derive(Clone, Copy)] +pub struct SighashAllReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SighashAllReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SighashAllReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SighashAllReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "message", self.message())?; + write!(f, ", {}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> SighashAllReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn message(&self) -> MessageReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + MessageReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn seal(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SighashAllReader<'r> { + type Entity = SighashAll; + const NAME: &'static str = "SighashAllReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SighashAllReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + MessageReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SighashAllBuilder { + pub(crate) message: Message, + pub(crate) seal: Bytes, +} +impl SighashAllBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn message(mut self, v: Message) -> Self { + self.message = v; + self + } + pub fn seal(mut self, v: Bytes) -> Self { + self.seal = v; + self + } +} +impl molecule::prelude::Builder for SighashAllBuilder { + type Entity = SighashAll; + const NAME: &'static str = "SighashAllBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.message.as_slice().len() + + self.seal.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.message.as_slice().len(); + offsets.push(total_size); + total_size += self.seal.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.message.as_slice())?; + writer.write_all(self.seal.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + SighashAll::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct SighashAllOnly(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for SighashAllOnly { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for SighashAllOnly { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for SighashAllOnly { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for SighashAllOnly { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + SighashAllOnly::new_unchecked(v) + } +} +impl SighashAllOnly { + const DEFAULT_VALUE: [u8; 12] = [12, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]; + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn seal(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> SighashAllOnlyReader<'r> { + SighashAllOnlyReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for SighashAllOnly { + type Builder = SighashAllOnlyBuilder; + const NAME: &'static str = "SighashAllOnly"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + SighashAllOnly(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SighashAllOnlyReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SighashAllOnlyReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().seal(self.seal()) + } +} +#[derive(Clone, Copy)] +pub struct SighashAllOnlyReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SighashAllOnlyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SighashAllOnlyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SighashAllOnlyReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> SighashAllOnlyReader<'r> { + pub const FIELD_COUNT: usize = 1; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn seal(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[8..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SighashAllOnlyReader<'r> { + type Entity = SighashAllOnly; + const NAME: &'static str = "SighashAllOnlyReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SighashAllOnlyReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + BytesReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SighashAllOnlyBuilder { + pub(crate) seal: Bytes, +} +impl SighashAllOnlyBuilder { + pub const FIELD_COUNT: usize = 1; + pub fn seal(mut self, v: Bytes) -> Self { + self.seal = v; + self + } +} +impl molecule::prelude::Builder for SighashAllOnlyBuilder { + type Entity = SighashAllOnly; + const NAME: &'static str = "SighashAllOnlyBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.seal.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.seal.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.seal.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + SighashAllOnly::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct SealPair(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for SealPair { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for SealPair { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for SealPair { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for SealPair { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + SealPair::new_unchecked(v) + } +} +impl SealPair { + const DEFAULT_VALUE: [u8; 48] = [ + 48, 0, 0, 0, 12, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn script_hash(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn seal(&self) -> Bytes { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + Bytes::new_unchecked(self.0.slice(start..end)) + } else { + Bytes::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> SealPairReader<'r> { + SealPairReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for SealPair { + type Builder = SealPairBuilder; + const NAME: &'static str = "SealPair"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + SealPair(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SealPairReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SealPairReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .script_hash(self.script_hash()) + .seal(self.seal()) + } +} +#[derive(Clone, Copy)] +pub struct SealPairReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SealPairReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SealPairReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SealPairReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "script_hash", self.script_hash())?; + write!(f, ", {}: {}", "seal", self.seal())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> SealPairReader<'r> { + pub const FIELD_COUNT: usize = 2; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn script_hash(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn seal(&self) -> BytesReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[12..]) as usize; + BytesReader::new_unchecked(&self.as_slice()[start..end]) + } else { + BytesReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SealPairReader<'r> { + type Entity = SealPair; + const NAME: &'static str = "SealPairReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SealPairReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + BytesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SealPairBuilder { + pub(crate) script_hash: Byte32, + pub(crate) seal: Bytes, +} +impl SealPairBuilder { + pub const FIELD_COUNT: usize = 2; + pub fn script_hash(mut self, v: Byte32) -> Self { + self.script_hash = v; + self + } + pub fn seal(mut self, v: Bytes) -> Self { + self.seal = v; + self + } +} +impl molecule::prelude::Builder for SealPairBuilder { + type Entity = SealPair; + const NAME: &'static str = "SealPairBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.script_hash.as_slice().len() + + self.seal.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.script_hash.as_slice().len(); + offsets.push(total_size); + total_size += self.seal.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.script_hash.as_slice())?; + writer.write_all(self.seal.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + SealPair::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct SealPairVec(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for SealPairVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for SealPairVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for SealPairVec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl ::core::default::Default for SealPairVec { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + SealPairVec::new_unchecked(v) + } +} +impl SealPairVec { + const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> SealPair { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + SealPair::new_unchecked(self.0.slice(start..)) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + SealPair::new_unchecked(self.0.slice(start..end)) + } + } + pub fn as_reader<'r>(&'r self) -> SealPairVecReader<'r> { + SealPairVecReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for SealPairVec { + type Builder = SealPairVecBuilder; + const NAME: &'static str = "SealPairVec"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + SealPairVec(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SealPairVecReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + SealPairVecReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().extend(self.into_iter()) + } +} +#[derive(Clone, Copy)] +pub struct SealPairVecReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for SealPairVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for SealPairVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for SealPairVecReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} [", Self::NAME)?; + for i in 0..self.len() { + if i == 0 { + write!(f, "{}", self.get_unchecked(i))?; + } else { + write!(f, ", {}", self.get_unchecked(i))?; + } + } + write!(f, "]") + } +} +impl<'r> SealPairVecReader<'r> { + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn item_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn len(&self) -> usize { + self.item_count() + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn get(&self, idx: usize) -> Option> { + if idx >= self.len() { + None + } else { + Some(self.get_unchecked(idx)) + } + } + pub fn get_unchecked(&self, idx: usize) -> SealPairReader<'r> { + let slice = self.as_slice(); + let start_idx = molecule::NUMBER_SIZE * (1 + idx); + let start = molecule::unpack_number(&slice[start_idx..]) as usize; + if idx == self.len() - 1 { + SealPairReader::new_unchecked(&self.as_slice()[start..]) + } else { + let end_idx = start_idx + molecule::NUMBER_SIZE; + let end = molecule::unpack_number(&slice[end_idx..]) as usize; + SealPairReader::new_unchecked(&self.as_slice()[start..end]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for SealPairVecReader<'r> { + type Entity = SealPairVec; + const NAME: &'static str = "SealPairVecReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + SealPairVecReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len == molecule::NUMBER_SIZE { + return Ok(()); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!( + Self, + TotalSizeNotMatch, + molecule::NUMBER_SIZE * 2, + slice_len + ); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + for pair in offsets.windows(2) { + let start = pair[0]; + let end = pair[1]; + SealPairReader::verify(&slice[start..end], compatible)?; + } + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct SealPairVecBuilder(pub(crate) Vec); +impl SealPairVecBuilder { + pub fn set(mut self, v: Vec) -> Self { + self.0 = v; + self + } + pub fn push(mut self, v: SealPair) -> Self { + self.0.push(v); + self + } + pub fn extend>(mut self, iter: T) -> Self { + for elem in iter { + self.0.push(elem); + } + self + } + pub fn replace(&mut self, index: usize, v: SealPair) -> Option { + self.0 + .get_mut(index) + .map(|item| ::core::mem::replace(item, v)) + } +} +impl molecule::prelude::Builder for SealPairVecBuilder { + type Entity = SealPairVec; + const NAME: &'static str = "SealPairVecBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (self.0.len() + 1) + + self + .0 + .iter() + .map(|inner| inner.as_slice().len()) + .sum::() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let item_count = self.0.len(); + if item_count == 0 { + writer.write_all(&molecule::pack_number( + molecule::NUMBER_SIZE as molecule::Number, + ))?; + } else { + let (total_size, offsets) = self.0.iter().fold( + ( + molecule::NUMBER_SIZE * (item_count + 1), + Vec::with_capacity(item_count), + ), + |(start, mut offsets), inner| { + offsets.push(start); + (start + inner.as_slice().len(), offsets) + }, + ); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + for inner in self.0.iter() { + writer.write_all(inner.as_slice())?; + } + } + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + SealPairVec::new_unchecked(inner.into()) + } +} +pub struct SealPairVecIterator(SealPairVec, usize, usize); +impl ::core::iter::Iterator for SealPairVecIterator { + type Item = SealPair; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl ::core::iter::ExactSizeIterator for SealPairVecIterator { + fn len(&self) -> usize { + self.2 - self.1 + } +} +impl ::core::iter::IntoIterator for SealPairVec { + type Item = SealPair; + type IntoIter = SealPairVecIterator; + fn into_iter(self) -> Self::IntoIter { + let len = self.len(); + SealPairVecIterator(self, 0, len) + } +} +impl<'r> SealPairVecReader<'r> { + pub fn iter<'t>(&'t self) -> SealPairVecReaderIterator<'t, 'r> { + SealPairVecReaderIterator(&self, 0, self.len()) + } +} +pub struct SealPairVecReaderIterator<'t, 'r>(&'t SealPairVecReader<'r>, usize, usize); +impl<'t: 'r, 'r> ::core::iter::Iterator for SealPairVecReaderIterator<'t, 'r> { + type Item = SealPairReader<'t>; + fn next(&mut self) -> Option { + if self.1 >= self.2 { + None + } else { + let ret = self.0.get_unchecked(self.1); + self.1 += 1; + Some(ret) + } + } +} +impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for SealPairVecReaderIterator<'t, 'r> { + fn len(&self) -> usize { + self.2 - self.1 + } +} +#[derive(Clone)] +pub struct OtxStart(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for OtxStart { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for OtxStart { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for OtxStart { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "start_input_cell", self.start_input_cell())?; + write!(f, ", {}: {}", "start_output_cell", self.start_output_cell())?; + write!(f, ", {}: {}", "start_cell_deps", self.start_cell_deps())?; + write!(f, ", {}: {}", "start_header_deps", self.start_header_deps())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for OtxStart { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + OtxStart::new_unchecked(v) + } +} +impl OtxStart { + const DEFAULT_VALUE: [u8; 36] = [ + 36, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 4; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn start_input_cell(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn start_output_cell(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn start_cell_deps(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn start_header_deps(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } else { + Uint32::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> OtxStartReader<'r> { + OtxStartReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for OtxStart { + type Builder = OtxStartBuilder; + const NAME: &'static str = "OtxStart"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + OtxStart(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + OtxStartReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + OtxStartReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .start_input_cell(self.start_input_cell()) + .start_output_cell(self.start_output_cell()) + .start_cell_deps(self.start_cell_deps()) + .start_header_deps(self.start_header_deps()) + } +} +#[derive(Clone, Copy)] +pub struct OtxStartReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for OtxStartReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for OtxStartReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for OtxStartReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "start_input_cell", self.start_input_cell())?; + write!(f, ", {}: {}", "start_output_cell", self.start_output_cell())?; + write!(f, ", {}: {}", "start_cell_deps", self.start_cell_deps())?; + write!(f, ", {}: {}", "start_header_deps", self.start_header_deps())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> OtxStartReader<'r> { + pub const FIELD_COUNT: usize = 4; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn start_input_cell(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn start_output_cell(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn start_cell_deps(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn start_header_deps(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Uint32Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for OtxStartReader<'r> { + type Entity = OtxStart; + const NAME: &'static str = "OtxStartReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + OtxStartReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Uint32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Uint32Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Uint32Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Uint32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct OtxStartBuilder { + pub(crate) start_input_cell: Uint32, + pub(crate) start_output_cell: Uint32, + pub(crate) start_cell_deps: Uint32, + pub(crate) start_header_deps: Uint32, +} +impl OtxStartBuilder { + pub const FIELD_COUNT: usize = 4; + pub fn start_input_cell(mut self, v: Uint32) -> Self { + self.start_input_cell = v; + self + } + pub fn start_output_cell(mut self, v: Uint32) -> Self { + self.start_output_cell = v; + self + } + pub fn start_cell_deps(mut self, v: Uint32) -> Self { + self.start_cell_deps = v; + self + } + pub fn start_header_deps(mut self, v: Uint32) -> Self { + self.start_header_deps = v; + self + } +} +impl molecule::prelude::Builder for OtxStartBuilder { + type Entity = OtxStart; + const NAME: &'static str = "OtxStartBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.start_input_cell.as_slice().len() + + self.start_output_cell.as_slice().len() + + self.start_cell_deps.as_slice().len() + + self.start_header_deps.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.start_input_cell.as_slice().len(); + offsets.push(total_size); + total_size += self.start_output_cell.as_slice().len(); + offsets.push(total_size); + total_size += self.start_cell_deps.as_slice().len(); + offsets.push(total_size); + total_size += self.start_header_deps.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.start_input_cell.as_slice())?; + writer.write_all(self.start_output_cell.as_slice())?; + writer.write_all(self.start_cell_deps.as_slice())?; + writer.write_all(self.start_header_deps.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + OtxStart::new_unchecked(inner.into()) + } +} +#[derive(Clone)] +pub struct Otx(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for Otx { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for Otx { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for Otx { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "input_cells", self.input_cells())?; + write!(f, ", {}: {}", "output_cells", self.output_cells())?; + write!(f, ", {}: {}", "cell_deps", self.cell_deps())?; + write!(f, ", {}: {}", "header_deps", self.header_deps())?; + write!(f, ", {}: {}", "message", self.message())?; + write!(f, ", {}: {}", "seals", self.seals())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for Otx { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + Otx::new_unchecked(v) + } +} +impl Otx { + const DEFAULT_VALUE: [u8; 60] = [ + 60, 0, 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 36, 0, 0, 0, 40, 0, 0, 0, 44, 0, 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, + ]; + pub const FIELD_COUNT: usize = 6; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn input_cells(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn output_cells(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn cell_deps(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn header_deps(&self) -> Uint32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32::new_unchecked(self.0.slice(start..end)) + } + pub fn message(&self) -> Message { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + Message::new_unchecked(self.0.slice(start..end)) + } + pub fn seals(&self) -> SealPairVec { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[28..]) as usize; + SealPairVec::new_unchecked(self.0.slice(start..end)) + } else { + SealPairVec::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> OtxReader<'r> { + OtxReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for Otx { + type Builder = OtxBuilder; + const NAME: &'static str = "Otx"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + Otx(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + OtxReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + OtxReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .input_cells(self.input_cells()) + .output_cells(self.output_cells()) + .cell_deps(self.cell_deps()) + .header_deps(self.header_deps()) + .message(self.message()) + .seals(self.seals()) + } +} +#[derive(Clone, Copy)] +pub struct OtxReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for OtxReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for OtxReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for OtxReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "input_cells", self.input_cells())?; + write!(f, ", {}: {}", "output_cells", self.output_cells())?; + write!(f, ", {}: {}", "cell_deps", self.cell_deps())?; + write!(f, ", {}: {}", "header_deps", self.header_deps())?; + write!(f, ", {}: {}", "message", self.message())?; + write!(f, ", {}: {}", "seals", self.seals())?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> OtxReader<'r> { + pub const FIELD_COUNT: usize = 6; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn input_cells(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn output_cells(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn cell_deps(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn header_deps(&self) -> Uint32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[16..]) as usize; + let end = molecule::unpack_number(&slice[20..]) as usize; + Uint32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn message(&self) -> MessageReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[20..]) as usize; + let end = molecule::unpack_number(&slice[24..]) as usize; + MessageReader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn seals(&self) -> SealPairVecReader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[24..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[28..]) as usize; + SealPairVecReader::new_unchecked(&self.as_slice()[start..end]) + } else { + SealPairVecReader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for OtxReader<'r> { + type Entity = Otx; + const NAME: &'static str = "OtxReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + OtxReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Uint32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Uint32Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Uint32Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Uint32Reader::verify(&slice[offsets[3]..offsets[4]], compatible)?; + MessageReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; + SealPairVecReader::verify(&slice[offsets[5]..offsets[6]], compatible)?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct OtxBuilder { + pub(crate) input_cells: Uint32, + pub(crate) output_cells: Uint32, + pub(crate) cell_deps: Uint32, + pub(crate) header_deps: Uint32, + pub(crate) message: Message, + pub(crate) seals: SealPairVec, +} +impl OtxBuilder { + pub const FIELD_COUNT: usize = 6; + pub fn input_cells(mut self, v: Uint32) -> Self { + self.input_cells = v; + self + } + pub fn output_cells(mut self, v: Uint32) -> Self { + self.output_cells = v; + self + } + pub fn cell_deps(mut self, v: Uint32) -> Self { + self.cell_deps = v; + self + } + pub fn header_deps(mut self, v: Uint32) -> Self { + self.header_deps = v; + self + } + pub fn message(mut self, v: Message) -> Self { + self.message = v; + self + } + pub fn seals(mut self, v: SealPairVec) -> Self { + self.seals = v; + self + } +} +impl molecule::prelude::Builder for OtxBuilder { + type Entity = Otx; + const NAME: &'static str = "OtxBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.input_cells.as_slice().len() + + self.output_cells.as_slice().len() + + self.cell_deps.as_slice().len() + + self.header_deps.as_slice().len() + + self.message.as_slice().len() + + self.seals.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.input_cells.as_slice().len(); + offsets.push(total_size); + total_size += self.output_cells.as_slice().len(); + offsets.push(total_size); + total_size += self.cell_deps.as_slice().len(); + offsets.push(total_size); + total_size += self.header_deps.as_slice().len(); + offsets.push(total_size); + total_size += self.message.as_slice().len(); + offsets.push(total_size); + total_size += self.seals.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.input_cells.as_slice())?; + writer.write_all(self.output_cells.as_slice())?; + writer.write_all(self.cell_deps.as_slice())?; + writer.write_all(self.header_deps.as_slice())?; + writer.write_all(self.message.as_slice())?; + writer.write_all(self.seals.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + Otx::new_unchecked(inner.into()) + } +} diff --git a/tests/omni_lock_rust/src/schemas/mod.rs b/tests/omni_lock_rust/src/schemas/mod.rs new file mode 100644 index 0000000..4fc5711 --- /dev/null +++ b/tests/omni_lock_rust/src/schemas/mod.rs @@ -0,0 +1,3 @@ +pub use ckb_types::packed as blockchain; +pub mod basic; +pub mod top_level; diff --git a/tests/omni_lock_rust/src/schemas/top_level.rs b/tests/omni_lock_rust/src/schemas/top_level.rs new file mode 100644 index 0000000..1bb527d --- /dev/null +++ b/tests/omni_lock_rust/src/schemas/top_level.rs @@ -0,0 +1,364 @@ +// Generated by Molecule 0.7.5 + +use super::basic::*; +use molecule::prelude::*; +#[derive(Clone)] +pub struct WitnessLayout(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for WitnessLayout { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for WitnessLayout { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for WitnessLayout { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl ::core::default::Default for WitnessLayout { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + WitnessLayout::new_unchecked(v) + } +} +impl WitnessLayout { + const DEFAULT_VALUE: [u8; 32] = [ + 1, 0, 0, 255, 28, 0, 0, 0, 12, 0, 0, 0, 24, 0, 0, 0, 12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, + ]; + pub const ITEMS_COUNT: usize = 4; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> WitnessLayoutUnion { + let inner = self.0.slice(molecule::NUMBER_SIZE..); + match self.item_id() { + 4278190081 => SighashAll::new_unchecked(inner).into(), + 4278190082 => SighashAllOnly::new_unchecked(inner).into(), + 4278190083 => Otx::new_unchecked(inner).into(), + 4278190084 => OtxStart::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } + pub fn as_reader<'r>(&'r self) -> WitnessLayoutReader<'r> { + WitnessLayoutReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for WitnessLayout { + type Builder = WitnessLayoutBuilder; + const NAME: &'static str = "WitnessLayout"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + WitnessLayout(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WitnessLayoutReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + WitnessLayoutReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder().set(self.to_enum()) + } +} +#[derive(Clone, Copy)] +pub struct WitnessLayoutReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for WitnessLayoutReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for WitnessLayoutReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for WitnessLayoutReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", Self::NAME)?; + self.to_enum().display_inner(f)?; + write!(f, ")") + } +} +impl<'r> WitnessLayoutReader<'r> { + pub const ITEMS_COUNT: usize = 4; + pub fn item_id(&self) -> molecule::Number { + molecule::unpack_number(self.as_slice()) + } + pub fn to_enum(&self) -> WitnessLayoutUnionReader<'r> { + let inner = &self.as_slice()[molecule::NUMBER_SIZE..]; + match self.item_id() { + 4278190081 => SighashAllReader::new_unchecked(inner).into(), + 4278190082 => SighashAllOnlyReader::new_unchecked(inner).into(), + 4278190083 => OtxReader::new_unchecked(inner).into(), + 4278190084 => OtxStartReader::new_unchecked(inner).into(), + _ => panic!("{}: invalid data", Self::NAME), + } + } +} +impl<'r> molecule::prelude::Reader<'r> for WitnessLayoutReader<'r> { + type Entity = WitnessLayout; + const NAME: &'static str = "WitnessLayoutReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + WitnessLayoutReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let item_id = molecule::unpack_number(slice); + let inner_slice = &slice[molecule::NUMBER_SIZE..]; + match item_id { + 4278190081 => SighashAllReader::verify(inner_slice, compatible), + 4278190082 => SighashAllOnlyReader::verify(inner_slice, compatible), + 4278190083 => OtxReader::verify(inner_slice, compatible), + 4278190084 => OtxStartReader::verify(inner_slice, compatible), + _ => ve!(Self, UnknownItem, Self::ITEMS_COUNT, item_id), + }?; + Ok(()) + } +} +#[derive(Debug, Default)] +pub struct WitnessLayoutBuilder(pub(crate) WitnessLayoutUnion); +impl WitnessLayoutBuilder { + pub const ITEMS_COUNT: usize = 4; + pub fn set(mut self, v: I) -> Self + where + I: ::core::convert::Into, + { + self.0 = v.into(); + self + } +} +impl molecule::prelude::Builder for WitnessLayoutBuilder { + type Entity = WitnessLayout; + const NAME: &'static str = "WitnessLayoutBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE + self.0.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + writer.write_all(&molecule::pack_number(self.0.item_id()))?; + writer.write_all(self.0.as_slice()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + WitnessLayout::new_unchecked(inner.into()) + } +} +#[derive(Debug, Clone)] +pub enum WitnessLayoutUnion { + SighashAll(SighashAll), + SighashAllOnly(SighashAllOnly), + Otx(Otx), + OtxStart(OtxStart), +} +#[derive(Debug, Clone, Copy)] +pub enum WitnessLayoutUnionReader<'r> { + SighashAll(SighashAllReader<'r>), + SighashAllOnly(SighashAllOnlyReader<'r>), + Otx(OtxReader<'r>), + OtxStart(OtxStartReader<'r>), +} +impl ::core::default::Default for WitnessLayoutUnion { + fn default() -> Self { + WitnessLayoutUnion::SighashAll(::core::default::Default::default()) + } +} +impl ::core::fmt::Display for WitnessLayoutUnion { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + WitnessLayoutUnion::SighashAll(ref item) => { + write!(f, "{}::{}({})", Self::NAME, SighashAll::NAME, item) + } + WitnessLayoutUnion::SighashAllOnly(ref item) => { + write!(f, "{}::{}({})", Self::NAME, SighashAllOnly::NAME, item) + } + WitnessLayoutUnion::Otx(ref item) => { + write!(f, "{}::{}({})", Self::NAME, Otx::NAME, item) + } + WitnessLayoutUnion::OtxStart(ref item) => { + write!(f, "{}::{}({})", Self::NAME, OtxStart::NAME, item) + } + } + } +} +impl<'r> ::core::fmt::Display for WitnessLayoutUnionReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + WitnessLayoutUnionReader::SighashAll(ref item) => { + write!(f, "{}::{}({})", Self::NAME, SighashAll::NAME, item) + } + WitnessLayoutUnionReader::SighashAllOnly(ref item) => { + write!(f, "{}::{}({})", Self::NAME, SighashAllOnly::NAME, item) + } + WitnessLayoutUnionReader::Otx(ref item) => { + write!(f, "{}::{}({})", Self::NAME, Otx::NAME, item) + } + WitnessLayoutUnionReader::OtxStart(ref item) => { + write!(f, "{}::{}({})", Self::NAME, OtxStart::NAME, item) + } + } + } +} +impl WitnessLayoutUnion { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + WitnessLayoutUnion::SighashAll(ref item) => write!(f, "{}", item), + WitnessLayoutUnion::SighashAllOnly(ref item) => write!(f, "{}", item), + WitnessLayoutUnion::Otx(ref item) => write!(f, "{}", item), + WitnessLayoutUnion::OtxStart(ref item) => write!(f, "{}", item), + } + } +} +impl<'r> WitnessLayoutUnionReader<'r> { + pub(crate) fn display_inner(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + WitnessLayoutUnionReader::SighashAll(ref item) => write!(f, "{}", item), + WitnessLayoutUnionReader::SighashAllOnly(ref item) => write!(f, "{}", item), + WitnessLayoutUnionReader::Otx(ref item) => write!(f, "{}", item), + WitnessLayoutUnionReader::OtxStart(ref item) => write!(f, "{}", item), + } + } +} +impl ::core::convert::From for WitnessLayoutUnion { + fn from(item: SighashAll) -> Self { + WitnessLayoutUnion::SighashAll(item) + } +} +impl ::core::convert::From for WitnessLayoutUnion { + fn from(item: SighashAllOnly) -> Self { + WitnessLayoutUnion::SighashAllOnly(item) + } +} +impl ::core::convert::From for WitnessLayoutUnion { + fn from(item: Otx) -> Self { + WitnessLayoutUnion::Otx(item) + } +} +impl ::core::convert::From for WitnessLayoutUnion { + fn from(item: OtxStart) -> Self { + WitnessLayoutUnion::OtxStart(item) + } +} +impl<'r> ::core::convert::From> for WitnessLayoutUnionReader<'r> { + fn from(item: SighashAllReader<'r>) -> Self { + WitnessLayoutUnionReader::SighashAll(item) + } +} +impl<'r> ::core::convert::From> for WitnessLayoutUnionReader<'r> { + fn from(item: SighashAllOnlyReader<'r>) -> Self { + WitnessLayoutUnionReader::SighashAllOnly(item) + } +} +impl<'r> ::core::convert::From> for WitnessLayoutUnionReader<'r> { + fn from(item: OtxReader<'r>) -> Self { + WitnessLayoutUnionReader::Otx(item) + } +} +impl<'r> ::core::convert::From> for WitnessLayoutUnionReader<'r> { + fn from(item: OtxStartReader<'r>) -> Self { + WitnessLayoutUnionReader::OtxStart(item) + } +} +impl WitnessLayoutUnion { + pub const NAME: &'static str = "WitnessLayoutUnion"; + pub fn as_bytes(&self) -> molecule::bytes::Bytes { + match self { + WitnessLayoutUnion::SighashAll(item) => item.as_bytes(), + WitnessLayoutUnion::SighashAllOnly(item) => item.as_bytes(), + WitnessLayoutUnion::Otx(item) => item.as_bytes(), + WitnessLayoutUnion::OtxStart(item) => item.as_bytes(), + } + } + pub fn as_slice(&self) -> &[u8] { + match self { + WitnessLayoutUnion::SighashAll(item) => item.as_slice(), + WitnessLayoutUnion::SighashAllOnly(item) => item.as_slice(), + WitnessLayoutUnion::Otx(item) => item.as_slice(), + WitnessLayoutUnion::OtxStart(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + WitnessLayoutUnion::SighashAll(_) => 4278190081, + WitnessLayoutUnion::SighashAllOnly(_) => 4278190082, + WitnessLayoutUnion::Otx(_) => 4278190083, + WitnessLayoutUnion::OtxStart(_) => 4278190084, + } + } + pub fn item_name(&self) -> &str { + match self { + WitnessLayoutUnion::SighashAll(_) => "SighashAll", + WitnessLayoutUnion::SighashAllOnly(_) => "SighashAllOnly", + WitnessLayoutUnion::Otx(_) => "Otx", + WitnessLayoutUnion::OtxStart(_) => "OtxStart", + } + } + pub fn as_reader<'r>(&'r self) -> WitnessLayoutUnionReader<'r> { + match self { + WitnessLayoutUnion::SighashAll(item) => item.as_reader().into(), + WitnessLayoutUnion::SighashAllOnly(item) => item.as_reader().into(), + WitnessLayoutUnion::Otx(item) => item.as_reader().into(), + WitnessLayoutUnion::OtxStart(item) => item.as_reader().into(), + } + } +} +impl<'r> WitnessLayoutUnionReader<'r> { + pub const NAME: &'r str = "WitnessLayoutUnionReader"; + pub fn as_slice(&self) -> &'r [u8] { + match self { + WitnessLayoutUnionReader::SighashAll(item) => item.as_slice(), + WitnessLayoutUnionReader::SighashAllOnly(item) => item.as_slice(), + WitnessLayoutUnionReader::Otx(item) => item.as_slice(), + WitnessLayoutUnionReader::OtxStart(item) => item.as_slice(), + } + } + pub fn item_id(&self) -> molecule::Number { + match self { + WitnessLayoutUnionReader::SighashAll(_) => 4278190081, + WitnessLayoutUnionReader::SighashAllOnly(_) => 4278190082, + WitnessLayoutUnionReader::Otx(_) => 4278190083, + WitnessLayoutUnionReader::OtxStart(_) => 4278190084, + } + } + pub fn item_name(&self) -> &str { + match self { + WitnessLayoutUnionReader::SighashAll(_) => "SighashAll", + WitnessLayoutUnionReader::SighashAllOnly(_) => "SighashAllOnly", + WitnessLayoutUnionReader::Otx(_) => "Otx", + WitnessLayoutUnionReader::OtxStart(_) => "OtxStart", + } + } +} diff --git a/tests/omni_lock_rust/tests/misc.rs b/tests/omni_lock_rust/tests/misc.rs index 6454416..75d4c9d 100644 --- a/tests/omni_lock_rust/tests/misc.rs +++ b/tests/omni_lock_rust/tests/misc.rs @@ -1,3 +1,4 @@ +use omni_lock_test::schemas::top_level::WitnessLayout; use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::rsa::Rsa; @@ -6,18 +7,16 @@ use sha3::{Digest, Keccak256}; use std::collections::HashMap; use std::convert::TryInto; -use ckb_chain_spec::consensus::{Consensus, ConsensusBuilder}; use ckb_crypto::secp::{Generator, Privkey, Pubkey}; use ckb_error::Error; use ckb_hash::{Blake2b, Blake2bBuilder}; use ckb_script::TxVerifyEnv; -use ckb_traits::{CellDataProvider, HeaderProvider}; +use ckb_traits::{CellDataProvider, ExtensionProvider, HeaderProvider}; use ckb_types::bytes::{BufMut, BytesMut}; use ckb_types::{ bytes::Bytes, core::{ cell::{CellMeta, CellMetaBuilder, ResolvedTransaction}, - hardfork::HardForkSwitch, Capacity, DepType, EpochNumberWithFraction, HeaderView, ScriptHashType, TransactionBuilder, TransactionView, }, @@ -39,12 +38,17 @@ use sparse_merkle_tree::default_store::DefaultStore; use sparse_merkle_tree::traits::Hasher; use sparse_merkle_tree::{SparseMerkleTree, H256}; +use ckb_chain_spec::consensus::ConsensusBuilder; +use ckb_script::TransactionScriptsVerifier; +use ckb_types::core::hardfork::HardForks; use omni_lock_test::omni_lock; use omni_lock_test::omni_lock::OmniLockWitnessLock; +use omni_lock_test::schemas::basic::{Message, SighashAll, SighashAllOnly}; use omni_lock_test::xudt_rce_mol::{ RCCellVecBuilder, RCDataBuilder, RCDataUnion, RCRuleBuilder, SmtProofBuilder, SmtProofEntryBuilder, SmtProofEntryVec, SmtProofEntryVecBuilder, }; +use std::sync::Arc; // on(1): white list // off(0): black list @@ -77,11 +81,16 @@ pub const ERROR_RCE_EMERGENCY_HALT: i8 = 54; pub const ERROR_RSA_VERIFY_FAILED: i8 = 42; pub const ERROR_INCORRECT_SINCE_VALUE: i8 = -24; pub const ERROR_ISO97962_INVALID_ARG9: i8 = 61; +pub const ERROR_MOL2_ERR_OVERFLOW: i8 = 8; // sudt supply errors pub const ERROR_EXCEED_SUPPLY: i8 = 90; pub const ERROR_SUPPLY_AMOUNT: i8 = 91; pub const ERROR_BURN: i8 = 92; pub const ERROR_NO_INFO_CELL: i8 = 93; +// cobuild +pub const ERROR_COBUILD_MOL2_ERR_DATA: i8 = 0x07; +pub const ERROR_SIGHASHALL_DUP: i8 = 113; +pub const MOL2_ERR_OVERFLOW: i8 = 8; // parse witnesses error // https://github.com/bitcoin-core/secp256k1/blob/d373bf6d08c82ac5496bf8103698c9f54d8d99d2/include/secp256k1.h#L219 pub const SECP256K1_TAG_PUBKEY_EVEN: u8 = 0x02; @@ -374,7 +383,7 @@ fn build_rc_rule(smt_root: &[u8; 32], is_black: bool, is_emergency: bool) -> Byt res.as_bytes() } -#[derive(Default)] +#[derive(Default, Clone)] pub struct DummyDataLoader { pub cells: HashMap, } @@ -415,6 +424,12 @@ impl HeaderProvider for DummyDataLoader { } } +impl ExtensionProvider for DummyDataLoader { + fn get_block_extension(&self, _hash: &packed::Byte32) -> Option { + None + } +} + pub fn blake160(message: &[u8]) -> Bytes { let r = ckb_hash::blake2b_256(message); Bytes::copy_from_slice(&r[..20]) @@ -609,44 +624,47 @@ pub fn sign_tx_by_input_group( let tx_hash = tx.hash(); let mut preimage_hash: Bytes = Default::default(); + let message = if config.cobuild_enabled { + cobuild_generate_signing_message_hash(&config.cobuild_message, dummy, &tx) + } else { + let mut blake2b = ckb_hash::new_blake2b(); + let mut message = [0u8; 32]; + blake2b.update(&tx_hash.raw_data()); + // digest the first witness + let witness = WitnessArgs::new_unchecked(tx.witnesses().get(begin_index).unwrap().unpack()); + let zero_lock = gen_zero_witness_lock( + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + config.sig_len, + config.preimage_len, + ); + + let witness_for_digest = witness + .clone() + .as_builder() + .lock(Some(zero_lock).pack()) + .build(); + let witness_len = witness_for_digest.as_bytes().len() as u64; + blake2b.update(&witness_len.to_le_bytes()); + blake2b.update(&witness_for_digest.as_bytes()); + ((begin_index + 1)..(begin_index + len)).for_each(|n| { + let witness = tx.witnesses().get(n).unwrap(); + let witness_len = witness.raw_data().len() as u64; + blake2b.update(&witness_len.to_le_bytes()); + blake2b.update(&witness.raw_data()); + }); + blake2b.finalize(&mut message); + message + }; + println!("origin message: {:02x?}", message); let mut signed_witnesses: Vec = tx .inputs() .into_iter() .enumerate() .map(|(i, _)| { if i == begin_index { - let mut blake2b = ckb_hash::new_blake2b(); - let mut message = [0u8; 32]; - blake2b.update(&tx_hash.raw_data()); - // digest the first witness - let witness = WitnessArgs::new_unchecked(tx.witnesses().get(i).unwrap().unpack()); - let zero_lock = gen_zero_witness_lock( - config.use_rc, - config.use_rc_identity, - &proof_vec, - &identity, - config.sig_len, - config.preimage_len, - ); - - let witness_for_digest = witness - .clone() - .as_builder() - .lock(Some(zero_lock).pack()) - .build(); - let witness_len = witness_for_digest.as_bytes().len() as u64; - blake2b.update(&witness_len.to_le_bytes()); - blake2b.update(&witness_for_digest.as_bytes()); - ((i + 1)..(i + len)).for_each(|n| { - let witness = tx.witnesses().get(n).unwrap(); - let witness_len = witness.raw_data().len() as u64; - blake2b.update(&witness_len.to_le_bytes()); - blake2b.update(&witness.raw_data()); - }); - blake2b.finalize(&mut message); - - println!("origin message: {:02x?}", message); - let message = if use_chain_confg(config.id.flags) { assert!(config.chain_config.is_some()); config @@ -657,9 +675,7 @@ pub fn sign_tx_by_input_group( } else { CkbH256::from(message) }; - println!("sign message: {:02x?}", message.as_bytes().to_vec()); - let witness_lock = if config.id.flags == IDENTITY_FLAGS_DL { let (mut sig, pubkey) = if config.use_rsa { rsa_sign(message.as_bytes(), &config.rsa_private_key) @@ -737,12 +753,52 @@ pub fn sign_tx_by_input_group( witness_lock.to_vec() ); - witness - .as_builder() - .lock(Some(witness_lock).pack()) - .build() - .as_bytes() - .pack() + if config.cobuild_enabled { + match &config.cobuild_message { + Some(msg) => { + let sighash_all = SighashAll::new_builder() + .message(msg.clone()) + .seal(witness_lock.pack()) + .build(); + let sighash_all = WitnessLayout::new_builder().set(sighash_all).build(); + let sighash_all = sighash_all.as_bytes(); + println!( + "sighash_all with enum id(size: {}): {:02x?}", + sighash_all.len(), + sighash_all.as_ref() + ); + let res = sighash_all.pack(); + println!("res(size: {}): {:02x?}", res.len(), res.as_bytes().as_ref()); + res + } + None => { + let sighash_all_only = SighashAllOnly::new_builder() + .seal(witness_lock.pack()) + .build(); + let sighash_all_only = + WitnessLayout::new_builder().set(sighash_all_only).build(); + let sighash_all_only = sighash_all_only.as_bytes(); + println!( + "sighash_all_only with enum id(size: {}): {:02x?}", + sighash_all_only.len(), + sighash_all_only.as_ref() + ); + let res = sighash_all_only.pack(); + println!("res(size: {}): {:02x?}", res.len(), res.as_bytes().as_ref()); + res + } + } + } else { + let witness = WitnessArgs::new_unchecked( + tx.witnesses().get(begin_index).unwrap().unpack(), + ); + witness + .as_builder() + .lock(Some(witness_lock).pack()) + .build() + .as_bytes() + .pack() + } } else { tx.witnesses().get(i).unwrap_or_default() } @@ -757,6 +813,16 @@ pub fn sign_tx_by_input_group( if preimage_hash.len() == 20 { write_back_preimage_hash(dummy, IDENTITY_FLAGS_DL, preimage_hash); } + + match &config.custom_extension_witnesses_beginning { + Some(ws) => { + let mut ws: Vec = ws.iter().map(|f| f.pack()).collect(); + ws.extend_from_slice(&signed_witnesses); + signed_witnesses = ws; + } + _ => {} + } + // calculate message tx.as_advanced_builder() .set_witnesses(signed_witnesses) @@ -955,6 +1021,14 @@ pub fn gen_tx_with_grouped_args( } } + match &config.custom_extension_witnesses { + Some(ws) => { + for w in ws { + tx_builder = tx_builder.witness(w.pack()); + } + } + _ => {} + }; tx_builder.build() } @@ -1450,6 +1524,10 @@ pub struct TestConfig { pub leading_witness_count: usize, pub chain_config: Option>, + pub cobuild_enabled: bool, + pub cobuild_message: Option, + pub custom_extension_witnesses: Option>, + pub custom_extension_witnesses_beginning: Option>, } #[derive(Copy, Clone, PartialEq)] @@ -1548,6 +1626,10 @@ impl TestConfig { leading_witness_count: 0, chain_config: None, + cobuild_enabled: false, + cobuild_message: Some(Message::default()), + custom_extension_witnesses: None, + custom_extension_witnesses_beginning: None, } } @@ -2000,17 +2082,6 @@ pub fn assert_script_error(err: Error, err_code: i8) { ); } -pub fn gen_consensus() -> Consensus { - let hardfork_switch = HardForkSwitch::new_without_any_enabled() - .as_builder() - .rfc_0232(200) - .build() - .unwrap(); - ConsensusBuilder::default() - .hardfork_switch(hardfork_switch) - .build() -} - pub fn gen_tx_env() -> TxVerifyEnv { let epoch = EpochNumberWithFraction::new(300, 0, 1); let header = HeaderView::new_advanced_builder() @@ -2040,3 +2111,74 @@ pub fn calculate_ripemd160(buf: &[u8]) -> [u8; 20] { pub fn bitcoin_hash160(buf: &[u8]) -> [u8; 20] { calculate_ripemd160(&calculate_sha256(buf)) } + +pub fn verify_tx( + resolved_tx: ResolvedTransaction, + data_loader: DummyDataLoader, +) -> TransactionScriptsVerifier { + let hard_fork = HardForks::new_mirana(); + let consensus = ConsensusBuilder::default() + .hardfork_switch(hard_fork) + .build(); + TransactionScriptsVerifier::new( + Arc::new(resolved_tx), + data_loader.clone(), + Arc::new(consensus), + Arc::new(TxVerifyEnv::new_commit( + &HeaderView::new_advanced_builder().build(), + )), + ) +} + +#[test] +fn test_gen_sign_msg() { + // generate_signing_message_hash(H256::from([1u8;32]), tx); +} + +pub fn cobuild_generate_signing_message_hash( + message: &Option, + data_loader: &mut DummyDataLoader, + tx: &TransactionView, +) -> [u8; 32] { + let mut count = 0; + // message + let mut hasher = match message { + Some(m) => { + let mut hasher = omni_lock_test::blake2b::new_sighash_all_blake2b(); + hasher.update(m.as_slice()); + count += m.as_slice().len(); + hasher + } + None => omni_lock_test::blake2b::new_sighash_all_only_blake2b(), + }; + // tx hash + hasher.update(tx.hash().as_slice()); + count += 32; + // inputs cell and data + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + hasher.update(&input_cell.as_slice()); + count += input_cell.as_slice().len(); + let input_cell_out_point = input_cell.previous_output(); + let (_, input_cell_data) = data_loader.cells.get(&input_cell_out_point).unwrap(); + hasher.update(&(input_cell_data.len() as u32).to_le_bytes()); + count += 4; + hasher.update(input_cell_data); + count += input_cell_data.len(); + } + // extra witnesses + for witness in tx.witnesses().into_iter().skip(inputs_len) { + hasher.update(&(witness.len() as u32).to_le_bytes()); + count += 4; + hasher.update(&witness.raw_data()); + count += witness.raw_data().len(); + } + println!( + "cobuild_generate_signing_message_hash totally hashed {} bytes", + count + ); + let mut result = [0u8; 32]; + hasher.finalize(&mut result); + result +} diff --git a/tests/omni_lock_rust/tests/test_anyone_can_pay.rs b/tests/omni_lock_rust/tests/test_anyone_can_pay.rs index 5f5b3e8..bf8a888 100644 --- a/tests/omni_lock_rust/tests/test_anyone_can_pay.rs +++ b/tests/omni_lock_rust/tests/test_anyone_can_pay.rs @@ -17,9 +17,9 @@ use rand::{thread_rng, Rng, SeedableRng}; use misc::{ assert_script_error, blake160, build_always_success_script, build_omni_lock_script, build_resolved_tx, debug_printer, gen_tx, gen_tx_with_grouped_args, gen_witness_lock, sign_tx, - sign_tx_by_input_group, sign_tx_hash, DummyDataLoader, TestConfig, TestScheme, ALWAYS_SUCCESS, - ERROR_DUPLICATED_INPUTS, ERROR_DUPLICATED_OUTPUTS, ERROR_ENCODING, ERROR_NO_PAIR, - ERROR_OUTPUT_AMOUNT_NOT_ENOUGH, ERROR_PUBKEY_BLAKE160_HASH, ERROR_WITNESS_SIZE, + sign_tx_by_input_group, sign_tx_hash, verify_tx, DummyDataLoader, TestConfig, TestScheme, + ALWAYS_SUCCESS, ERROR_DUPLICATED_INPUTS, ERROR_DUPLICATED_OUTPUTS, ERROR_ENCODING, + ERROR_NO_PAIR, ERROR_OUTPUT_AMOUNT_NOT_ENOUGH, ERROR_PUBKEY_BLAKE160_HASH, ERROR_WITNESS_SIZE, IDENTITY_FLAGS_PUBKEY_HASH, MAX_CYCLES, OMNI_LOCK, }; @@ -27,8 +27,6 @@ mod misc; #[test] fn test_unlock_by_anyone() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -48,8 +46,7 @@ fn test_unlock_by_anyone() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass"); @@ -57,8 +54,6 @@ fn test_unlock_by_anyone() { #[test] fn test_put_output_data() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -79,8 +74,7 @@ fn test_put_output_data() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_ENCODING); @@ -88,8 +82,6 @@ fn test_put_output_data() { #[test] fn test_wrong_output_args() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -110,8 +102,7 @@ fn test_wrong_output_args() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_NO_PAIR); @@ -119,8 +110,6 @@ fn test_wrong_output_args() { #[test] fn test_split_cell() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -152,8 +141,7 @@ fn test_split_cell() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_DUPLICATED_OUTPUTS); @@ -161,8 +149,6 @@ fn test_split_cell() { #[test] fn test_merge_cell() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -183,8 +169,7 @@ fn test_merge_cell() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_DUPLICATED_INPUTS); @@ -192,8 +177,6 @@ fn test_merge_cell() { #[test] fn test_insufficient_pay() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -214,8 +197,7 @@ fn test_insufficient_pay() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_OUTPUT_AMOUNT_NOT_ENOUGH); @@ -223,8 +205,6 @@ fn test_insufficient_pay() { #[test] fn test_payment_not_meet_requirement() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((1, 0))); @@ -245,8 +225,7 @@ fn test_payment_not_meet_requirement() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_OUTPUT_AMOUNT_NOT_ENOUGH); @@ -254,8 +233,6 @@ fn test_payment_not_meet_requirement() { #[test] fn test_no_pair() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -275,8 +252,7 @@ fn test_no_pair() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_NO_PAIR); @@ -284,8 +260,6 @@ fn test_no_pair() { #[test] fn test_overflow() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((255, 0))); @@ -305,8 +279,7 @@ fn test_overflow() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_OUTPUT_AMOUNT_NOT_ENOUGH); @@ -314,8 +287,6 @@ fn test_overflow() { #[test] fn test_only_pay_ckb() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); // do not accept UDT transfer @@ -348,8 +319,7 @@ fn test_only_pay_ckb() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass"); @@ -357,8 +327,6 @@ fn test_only_pay_ckb() { #[test] fn test_only_pay_udt() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); // do not accept CKB transfer @@ -392,8 +360,7 @@ fn test_only_pay_udt() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass"); @@ -401,8 +368,6 @@ fn test_only_pay_udt() { #[test] fn test_udt_unlock_by_anyone() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -434,8 +399,7 @@ fn test_udt_unlock_by_anyone() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass"); @@ -443,8 +407,6 @@ fn test_udt_unlock_by_anyone() { #[test] fn test_udt_overflow() { - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); // do not accept CKB transfer @@ -477,8 +439,7 @@ fn test_udt_overflow() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_OUTPUT_AMOUNT_NOT_ENOUGH); @@ -487,8 +448,7 @@ fn test_udt_overflow() { #[test] fn test_extended_udt() { // we assume the first 16 bytes data represent token amount - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); + let mut data_loader = DummyDataLoader::new(); let mut config = TestConfig::new(IDENTITY_FLAGS_PUBKEY_HASH, false); config.set_acp_config(Some((0, 0))); @@ -525,8 +485,7 @@ fn test_extended_udt() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass"); diff --git a/tests/omni_lock_rust/tests/test_multisig.rs b/tests/omni_lock_rust/tests/test_multisig.rs index 0c41884..af60e3b 100644 --- a/tests/omni_lock_rust/tests/test_multisig.rs +++ b/tests/omni_lock_rust/tests/test_multisig.rs @@ -10,16 +10,14 @@ use ckb_script::{ScriptError, ScriptGroupType, TransactionScriptsVerifier, TxVer use ckb_types::{ bytes::Bytes, bytes::BytesMut, - core::{ - cell::ResolvedTransaction, hardfork::HardForkSwitch, EpochNumberWithFraction, HeaderView, - }, + core::{cell::ResolvedTransaction, HeaderView}, packed::WitnessArgs, prelude::*, H256, }; use lazy_static::lazy_static; use misc::*; -use omni_lock_test::debug_utils::debug; +// use omni_lock_test::debug_utils::debug; use std::fs; // Script args validation errors @@ -43,10 +41,7 @@ fn test_multisig_0_2_3_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -67,11 +62,7 @@ fn test_multisig_invalid_flags() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_MULTSIG_SCRIPT_HASH) @@ -91,11 +82,7 @@ fn test_multisig_invalid_flags2() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_MULTSIG_SCRIPT_HASH) @@ -114,11 +101,7 @@ fn test_multisig_1_2_3_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -137,11 +120,7 @@ fn test_multisig_3_7_15_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -160,11 +139,7 @@ fn test_multisig_0_1_1_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -183,11 +158,7 @@ fn test_multisig_0_2_2_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -196,8 +167,8 @@ fn test_multisig_0_2_2_unlock() { #[test] #[ignore] fn test_multisig_0_2_3_unlock_smt_in_input_debug() { - let binary = fs::read("../../../build/omni_lock.debug").expect("read_to_string"); - let omni_lock_debug = Bytes::from(binary); + // let binary = fs::read("../../../build/omni_lock.debug").expect("read_to_string"); + // let omni_lock_debug = Bytes::from(binary); let mut data_loader = DummyDataLoader::new(); @@ -211,21 +182,17 @@ fn test_multisig_0_2_3_unlock_smt_in_input_debug() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); - debug( - "127.0.0.1:9999", - ScriptGroupType::Lock, - config.running_script.calc_script_hash(), - &omni_lock_debug, - &[], - &verifier, - ); + // debug( + // "127.0.0.1:9999", + // ScriptGroupType::Lock, + // config.running_script.calc_script_hash(), + // &omni_lock_debug, + // &[], + // &verifier, + // ); } #[test] @@ -242,11 +209,71 @@ fn test_multisig_0_2_3_unlock_smt_in_input() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } + +#[test] +fn test_cobuild_multisig_0_2_3_unlock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_MULTISIG, true); + config.cobuild_enabled = true; + config.set_multisig(0, 2, 3); + + config.scheme = TestScheme::OnWhiteList; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_multisig_invalid_flags() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_MULTISIG, true); + config.set_multisig(0, 2, 3); + config.multisig.set(0, 2, 4); + config.cobuild_enabled = true; + + config.scheme = TestScheme::OnWhiteList; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MULTSIG_SCRIPT_HASH) +} + +#[test] +fn test_cobuild_multisig_invalid_flags2() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_MULTISIG, true); + config.set_multisig(0, 2, 3); + config.multisig.set(0, 3, 3); + config.cobuild_enabled = true; + + config.scheme = TestScheme::OnWhiteList; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MULTSIG_SCRIPT_HASH) +} diff --git a/tests/omni_lock_rust/tests/test_omni_lock.rs b/tests/omni_lock_rust/tests/test_omni_lock.rs index 69649d5..52c0f27 100644 --- a/tests/omni_lock_rust/tests/test_omni_lock.rs +++ b/tests/omni_lock_rust/tests/test_omni_lock.rs @@ -3,22 +3,27 @@ mod misc; +use std::fs::File; +use std::io::Read; + +use blake2b_rs::{Blake2b, Blake2bBuilder}; use ckb_chain_spec::consensus::ConsensusBuilder; use ckb_crypto::secp::Generator; use ckb_error::assert_error_eq; use ckb_script::{ScriptError, TransactionScriptsVerifier, TxVerifyEnv}; +use ckb_types::core::hardfork::HardForks; use ckb_types::{ bytes::Bytes, bytes::BytesMut, - core::{ - cell::ResolvedTransaction, hardfork::HardForkSwitch, EpochNumberWithFraction, HeaderView, - }, + core::{cell::ResolvedTransaction, EpochNumberWithFraction, HeaderView}, packed::WitnessArgs, prelude::*, H256, }; use lazy_static::lazy_static; use misc::*; +use omni_lock_test::schemas::{basic::*, blockchain::WitnessArgsBuilder, top_level::*}; +use std::sync::Arc; // // owner lock section @@ -35,12 +40,9 @@ fn test_simple_owner_lock() { // For ckb 0.40.0 // let mut verifier = - // TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + // TransactionScriptsVerifier::new(&resolved_tx, data_loader); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -58,10 +60,7 @@ fn test_owner_lock_without_witness() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -79,10 +78,7 @@ fn test_simple_owner_lock_mismatched() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -100,10 +96,7 @@ fn test_owner_lock_on_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -122,10 +115,7 @@ fn test_owner_lock_on_wl_without_witness() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -143,10 +133,7 @@ fn test_owner_lock_not_on_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -166,10 +153,7 @@ fn test_owner_lock_no_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -187,10 +171,7 @@ fn test_owner_lock_on_bl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -208,10 +189,7 @@ fn test_owner_lock_emergency_halt_mode() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -233,10 +211,7 @@ fn test_pubkey_hash_on_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -255,10 +230,7 @@ fn test_pubkey_hash_without_omni_identity() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -277,10 +249,7 @@ fn test_pubkey_hash_on_wl_without_witness() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -298,11 +267,7 @@ fn test_pubkey_hash_not_on_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_NOT_ON_WHITE_LIST) @@ -321,11 +286,7 @@ fn test_pubkey_hash_no_wl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_NO_WHITE_LIST) @@ -342,11 +303,7 @@ fn test_pubkey_hash_on_bl() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_ON_BLACK_LIST) @@ -363,11 +320,7 @@ fn test_pubkey_hash_emergency_halt_mode() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_RCE_EMERGENCY_HALT) @@ -384,10 +337,7 @@ fn test_rsa_via_dl_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -405,10 +355,7 @@ fn test_rsa_via_dl_wrong_sig() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_RSA_VERIFY_FAILED); @@ -428,10 +375,7 @@ fn test_rsa_via_dl_unlock_with_time_lock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -451,10 +395,7 @@ fn test_rsa_via_dl_unlock_with_time_lock_failed() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); @@ -474,10 +415,7 @@ fn test_iso9796_2_batch_via_dl_unlock_failed() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = gen_consensus(); - let tx_env = gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert!(verify_result.is_err()); @@ -494,11 +432,7 @@ fn test_eth_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -517,11 +451,27 @@ fn test_btc_success(vtype: u8) { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +fn test_cobuild_btc_success(vtype: u8) { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: vtype, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -540,11 +490,7 @@ fn test_btc_err_pubkey(vtype: u8) { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert!(verify_result.is_err()); @@ -564,6 +510,11 @@ fn test_btc_unlock() { test_btc(BITCOIN_V_TYPE_SEGWITBECH32); } +#[test] +fn test_cobuild_btc_native_segwit() { + test_cobuild_btc_success(BITCOIN_V_TYPE_P2PKHCOMPRESSED); +} + #[test] fn test_dogecoin_unlock() { let mut data_loader = DummyDataLoader::new(); @@ -575,11 +526,7 @@ fn test_dogecoin_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -598,11 +545,7 @@ fn test_dogecoin_err_pubkey() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert!(verify_result.is_err()) @@ -620,11 +563,7 @@ fn test_eos_success(vtype: u8) { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -643,11 +582,7 @@ fn test_eos_err_pubkey(vtype: u8) { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert!(verify_result.is_err()); @@ -676,11 +611,7 @@ fn test_tron_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -699,11 +630,7 @@ fn test_tron_err_pubkey() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); assert!(verify_result.is_err()); @@ -721,11 +648,732 @@ fn test_eth_displaying_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +// 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!( + "519b7adaa5a4b585d15aa14fe605d55b2e71235b8c4868784a3553d4d034a929", + &actual_hash + ); +} + +#[test] +fn test_cobuild_no_has_message() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses = Some(vec![Bytes::from([00, 00].to_vec())]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_append_witnessed_less_than_4() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses = Some(vec![ + Bytes::from([00, 01, 00].to_vec()), + Bytes::from([00, 00, 00, 00].to_vec()), + Bytes::new(), + ]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_non_empty_witness() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let lock_args = config.gen_args(); + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(lock_args, 2)], &mut config); + + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MOL2_ERR_OVERFLOW); +} + +#[test] +fn test_cobuild_input_cell_data_size_0() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_input_cell_data_size_1() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 1])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_input_cell_data_size_2048() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 2048])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_input_cell_data_size_2049() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 2049])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_input_cell_data_size_500k() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + ( + input_cell_output.clone(), + Bytes::from(vec![0x42; 500 * 1024]), + ), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_wrong_union_id() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + + let witness = tx.witnesses().get(0).unwrap(); + let mut witness_builder = witness.as_builder(); + witness_builder.replace(0, 0x03.into()); + let witness = witness_builder.build(); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![witness]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MOL2_ERR_OVERFLOW); +} + +#[test] +fn test_cobuild_sighash_all_only() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.cobuild_message = None; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_append_witnessargs() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses = Some(vec![WitnessArgsBuilder::default() + .lock(Some(Bytes::from([0u8; 65].to_vec())).pack()) + .build() + .as_bytes()]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_append_other_witnesslayout() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses = Some(vec![WitnessLayoutBuilder::default() + .set(WitnessLayoutUnion::SighashAllOnly( + SighashAllOnlyBuilder::default() + .seal(Bytes::from([0u8; 32].to_vec()).pack()) + .build(), + )) + .build() + .as_bytes()]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_sighashall_dup() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + const WSITNESS_LAYOUT_SIGHASH_ALL: u32 = 4278190081; + let mut witness = Vec::new(); + witness.resize(6, 0); + witness[..4].copy_from_slice(&WSITNESS_LAYOUT_SIGHASH_ALL.to_le_bytes()); + + config.custom_extension_witnesses = Some(vec![Bytes::from(witness)]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), MOL2_ERR_OVERFLOW); +} + +#[test] +fn test_cobuild_no_cobuild_append_sighash_all() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses = Some(vec![Bytes::from( + WitnessLayoutBuilder::default() + .set(WitnessLayoutUnion::SighashAll( + SighashAllBuilder::default() + .message(MessageBuilder::default().build()) + .seal(Bytes::from([0u8; 32].to_vec()).pack()) + .build(), + )) + .build() + .as_bytes(), + )]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_insert_witness_less_4_before_sighashall() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + config.custom_extension_witnesses_beginning = Some(vec![Bytes::from([00, 01, 02].to_vec())]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.unwrap_err(); +} + +#[test] +fn test_cobuild_big_message() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + + let mut action_vec = Vec::::new(); + for _ in 0..3072 { + let action_builder = Action::new_builder(); + let action_builder = action_builder.script_info_hash( + ckb_types::packed::Byte32::new_unchecked(Bytes::from(vec![0x00; 32])), + ); + let action_builder = action_builder.script_hash(ckb_types::packed::Byte32::new_unchecked( + Bytes::from(vec![0x00; 32]), + )); + let action_builder = action_builder.data(ckb_types::packed::Bytes::new_unchecked( + Bytes::from(vec![0x42; 128]), + )); + let action = action_builder.build(); + action_vec.push(action); + } + let action_vec = ActionVec::new_builder().extend(action_vec).build(); + let message = Message::new_builder().actions(action_vec).build(); + config.cobuild_message = Some(message); // Message is 651300 bytes in molecule type. + + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_simple_owner_lock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_OWNER_LOCK, false); + config.cobuild_enabled = true; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_simple_owner_lock_mismatched() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_OWNER_LOCK, false); + config.cobuild_enabled = true; + config.scheme = TestScheme::OwnerLockMismatched; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_LOCK_SCRIPT_HASH_NOT_FOUND) +} + +#[test] +fn test_cobuild_owner_lock_on_wl() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_OWNER_LOCK, true); + config.cobuild_enabled = true; + config.scheme = TestScheme::OnWhiteList; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_owner_lock_on_wl_without_witness() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_OWNER_LOCK, true); + config.cobuild_enabled = true; + config.scheme = TestScheme::OnWhiteList; + config.scheme2 = TestScheme2::NoWitness; + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert!(verify_result.is_err()); +} + +#[test] +fn test_cobuild_rsa_via_dl_unlock_with_time_lock() { + let mut data_loader = DummyDataLoader::new(); + + let args_since = 0x2000_0000_0000_0000u64 + 200; + let input_since = 0x2000_0000_0000_0000u64 + 200; + let mut config = TestConfig::new(IDENTITY_FLAGS_DL, false); + config.cobuild_enabled = true; + config.set_rsa(); + config.set_since(args_since, input_since); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_rsa_via_dl_unlock_with_time_lock_failed() { + let mut data_loader = DummyDataLoader::new(); + + let args_since = 0x2000_0000_0000_0000u64 + 200; + let input_since = 0x2000_0000_0000_0000u64 + 100; + let mut config = TestConfig::new(IDENTITY_FLAGS_DL, false); + config.cobuild_enabled = true; + config.set_rsa(); + config.set_since(args_since, input_since); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + + assert_script_error(verify_result.unwrap_err(), ERROR_INCORRECT_SINCE_VALUE); +} + +#[test] +fn test_cobuild_append_witnessargs_acp() { + let mut data_loader: DummyDataLoader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + config.set_acp_config(Some((0, 0))); + + config.custom_extension_witnesses = Some(vec![WitnessArgsBuilder::default() + .lock(Some(Bytes::from([0u8; 65].to_vec())).pack()) + .build() + .as_bytes()]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_append_witnessargs_since() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let args_since = 0x2000_0000_0000_0000u64 + 200; + let input_since = 0x2000_0000_0000_0000u64 + 200; + config.set_since(args_since, input_since); + + config.custom_extension_witnesses = Some(vec![WitnessArgsBuilder::default() + .lock(Some(Bytes::from([0u8; 65].to_vec())).pack()) + .build() + .as_bytes()]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_append_other_witnesslayout_acp() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + config.set_acp_config(Some((0, 0))); + + config.custom_extension_witnesses = Some(vec![WitnessLayoutBuilder::default() + .set(WitnessLayoutUnion::SighashAllOnly( + SighashAllOnlyBuilder::default() + .seal(Bytes::from([0u8; 32].to_vec()).pack()) + .build(), + )) + .build() + .as_bytes()]); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_eth_unlock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_ETHEREUM, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(EthereumConfig::default())); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_cobuild_eth_displaying_unlock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_ETHEREUM_DISPLAYING, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(EthereumDisplayConfig::default())); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); diff --git a/tests/omni_lock_rust/tests/test_secp256k1_compatibility.rs b/tests/omni_lock_rust/tests/test_secp256k1_compatibility.rs index 08e358a..940e316 100644 --- a/tests/omni_lock_rust/tests/test_secp256k1_compatibility.rs +++ b/tests/omni_lock_rust/tests/test_secp256k1_compatibility.rs @@ -8,9 +8,7 @@ use ckb_script::{ScriptError, TransactionScriptsVerifier, TxVerifyEnv}; use ckb_types::{ bytes::Bytes, bytes::BytesMut, - core::{ - cell::ResolvedTransaction, hardfork::HardForkSwitch, EpochNumberWithFraction, HeaderView, - }, + core::{cell::ResolvedTransaction, EpochNumberWithFraction, HeaderView}, packed::WitnessArgs, prelude::*, H256, @@ -21,7 +19,7 @@ use rand::{thread_rng, Rng, SeedableRng}; use misc::{ assert_script_error, blake160, build_resolved_tx, debug_printer, gen_tx, gen_tx_with_grouped_args, gen_witness_lock, sign_tx, sign_tx_by_input_group, sign_tx_hash, - DummyDataLoader, TestConfig, TestScheme, ERROR_ENCODING, ERROR_PUBKEY_BLAKE160_HASH, + verify_tx, DummyDataLoader, TestConfig, TestScheme, ERROR_ENCODING, ERROR_PUBKEY_BLAKE160_HASH, ERROR_WITNESS_SIZE, IDENTITY_FLAGS_PUBKEY_HASH, MAX_CYCLES, }; @@ -39,11 +37,7 @@ fn test_sighash_all_unlock() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -59,11 +53,7 @@ fn test_sighash_all_unlock_with_args() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -88,11 +78,7 @@ fn test_sighash_all_with_extra_witness_unlock() { let tx = sign_tx(&mut data_loader, tx.clone(), &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader.clone()); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } @@ -114,11 +100,7 @@ fn test_sighash_all_with_extra_witness_unlock() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader.clone()); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -136,11 +118,7 @@ fn test_sighash_all_with_grouped_inputs_unlock() { let tx = sign_tx(&mut data_loader, tx.clone(), &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader.clone()); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } @@ -165,11 +143,7 @@ fn test_sighash_all_with_grouped_inputs_unlock() { .build(); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -191,10 +165,7 @@ fn test_sighash_all_with_2_different_inputs_unlock() { let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } @@ -211,10 +182,7 @@ fn test_signing_with_wrong_key() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -234,10 +202,7 @@ fn test_signing_wrong_tx_hash() { }; let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -253,11 +218,7 @@ fn test_super_long_witness() { let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); @@ -283,11 +244,7 @@ fn test_sighash_all_2_in_2_out_cycles() { let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); let cycles = verify_result.expect("pass verification"); @@ -322,10 +279,7 @@ fn test_sighash_all_witness_append_junk_data() { let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -365,10 +319,7 @@ fn test_sighash_all_witness_args_ambiguity() { let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -409,10 +360,7 @@ fn test_sighash_all_witnesses_ambiguity() { assert_eq!(tx.witnesses().len(), tx.inputs().len()); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(MAX_CYCLES); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } @@ -448,10 +396,7 @@ fn test_sighash_all_cover_extra_witnesses() { let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let verifier = TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let verifier = verify_tx(resolved_tx, data_loader); let verify_result = verifier.verify(60000000); assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH) } diff --git a/tests/omni_lock_rust/tests/test_sudt_supply.rs b/tests/omni_lock_rust/tests/test_sudt_supply.rs index 7473287..a155d07 100644 --- a/tests/omni_lock_rust/tests/test_sudt_supply.rs +++ b/tests/omni_lock_rust/tests/test_sudt_supply.rs @@ -1,6 +1,5 @@ #![allow(dead_code)] -use ckb_script::TransactionScriptsVerifier; use ckb_types::{ bytes::Bytes, core::{Capacity, DepType, ScriptHashType, TransactionView}, @@ -11,8 +10,8 @@ use rand::{thread_rng, Rng}; use misc::{ assert_script_error, build_always_success_script, build_resolved_tx, debug_printer, gen_tx, - sign_tx, DummyDataLoader, EthereumConfig, TestConfig, ALWAYS_SUCCESS, CKB_INVALID_DATA, - ERROR_BURN, ERROR_EXCEED_SUPPLY, ERROR_NO_INFO_CELL, ERROR_SUPPLY_AMOUNT, + sign_tx, verify_tx, DummyDataLoader, EthereumConfig, TestConfig, ALWAYS_SUCCESS, + CKB_INVALID_DATA, ERROR_BURN, ERROR_EXCEED_SUPPLY, ERROR_NO_INFO_CELL, ERROR_SUPPLY_AMOUNT, IDENTITY_FLAGS_ETHEREUM, MAX_CYCLES, SIMPLE_UDT, }; @@ -182,11 +181,7 @@ where let tx = sign_tx(&mut data_loader, tx, &mut config); let resolved_tx = build_resolved_tx(&data_loader, &tx); - let consensus = misc::gen_consensus(); - let tx_env = misc::gen_tx_env(); - let mut verifier = - TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); - + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); if error_code == 0 { @@ -713,3 +708,109 @@ fn test_info_cell_max_supply_changed() { tx }); } + +fn run_sudt_supply_case_cobuild(error_code: i8, gen_tx_fn: F) +where + F: Fn(&mut DummyDataLoader, &mut TestConfig) -> TransactionView, +{ + let mut data_loader = DummyDataLoader::new(); + let mut config = TestConfig::new(IDENTITY_FLAGS_ETHEREUM, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(EthereumConfig::default())); + + let tx = gen_tx_fn(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader.clone()); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + if error_code == 0 { + verify_result.expect("pass verification"); + } else { + assert_script_error(verify_result.unwrap_err(), error_code); + } +} + +// ==== SUCCESS cases ==== +#[test] +fn test_cobuild_success_issue_token() { + run_sudt_supply_case_cobuild(0, |data_loader, config| { + let (info_cell_type_script, cell_id) = gen_info_cell_type_script(); + config.set_sudt_supply(cell_id); + + let mut tx = gen_tx(data_loader, config); + let issue_amount: u128 = 336; + let max_supply: u128 = 6000; + let sudt_type_script = sudt_type_script(data_loader, &tx); + let sudt_type_script_hash = sudt_type_script.calc_script_hash(); + tx = add_sudt_dep(data_loader, tx); + tx = add_sudt_to_outputs(sudt_type_script.clone(), tx, issue_amount); + let input_info_cell_data = + build_info_cell_data(20, max_supply, sudt_type_script_hash.as_slice()); + let output_info_cell_data = build_info_cell_data( + 20 + issue_amount, + max_supply, + sudt_type_script_hash.as_slice(), + ); + tx = add_info_cell_to_inputs( + data_loader, + info_cell_type_script.clone(), + tx, + input_info_cell_data, + ); + tx = add_info_cell_to_outputs(info_cell_type_script.clone(), tx, output_info_cell_data); + tx + }); +} + +// ==== ERROR cases ==== +#[test] +fn test_cobuild_burn_token() { + run_sudt_supply_case_cobuild(ERROR_BURN, |data_loader, config| { + let (info_cell_type_script, cell_id) = gen_info_cell_type_script(); + config.set_sudt_supply(cell_id); + + let mut tx = gen_tx(data_loader, config); + let max_supply: u128 = 6000; + let sudt_type_script = sudt_type_script(data_loader, &tx); + let sudt_type_script_hash = sudt_type_script.calc_script_hash(); + tx = add_sudt_dep(data_loader, tx); + tx = add_sudt_to_inputs(data_loader, sudt_type_script.clone(), tx, 200); + let input_info_cell_data = + build_info_cell_data(400, max_supply, sudt_type_script_hash.as_slice()); + let output_info_cell_data = + build_info_cell_data(200, max_supply, sudt_type_script_hash.as_slice()); + tx = add_info_cell_to_inputs( + data_loader, + info_cell_type_script.clone(), + tx, + input_info_cell_data, + ); + tx = add_info_cell_to_outputs(info_cell_type_script.clone(), tx, output_info_cell_data); + tx + }); +} + +#[test] +fn test_cobuild_no_info_cell_in_inputs() { + run_sudt_supply_case_cobuild(ERROR_NO_INFO_CELL, |data_loader, config| { + let (info_cell_type_script, cell_id) = gen_info_cell_type_script(); + config.set_sudt_supply(cell_id); + + let mut tx = gen_tx(data_loader, config); + let issue_amount: u128 = 336; + let max_supply: u128 = 6000; + let sudt_type_script = sudt_type_script(data_loader, &tx); + let sudt_type_script_hash = sudt_type_script.calc_script_hash(); + tx = add_sudt_dep(data_loader, tx); + tx = add_sudt_to_outputs(sudt_type_script.clone(), tx, issue_amount); + let output_info_cell_data = build_info_cell_data( + 20 + issue_amount, + max_supply, + sudt_type_script_hash.as_slice(), + ); + tx = add_info_cell_to_outputs(info_cell_type_script.clone(), tx, output_info_cell_data); + tx + }); +}