Skip to content

Commit

Permalink
Add utilities functions
Browse files Browse the repository at this point in the history
  • Loading branch information
XuJiandong committed Jan 15, 2024
1 parent bcd9b58 commit 261283c
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 92 deletions.
17 changes: 12 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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


Expand Down Expand Up @@ -54,7 +54,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)"
Expand All @@ -76,17 +77,23 @@ 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 $@


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:
Expand Down
61 changes: 61 additions & 0 deletions c/blake2b_decl_only.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

#ifndef __BLAKE2B_DECL_ONLY_H__
#define __BLAKE2B_DECL_ONLY_H__

#include <stddef.h>
#include <stdint.h>

#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
227 changes: 227 additions & 0 deletions c/cobuild.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
// clang-format off
#define CKB_DECLARATION_ONLY
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "cobuild.h"

#define MOLECULEC_C2_DECLARATION_ONLY
#define MOLECULEC2_VERSION 6001
#define MOLECULE2_API_VERSION_MIN 5000
#include "molecule2_reader.h"

#include "blake2b_decl_only.h"
#include "ckb_consts.h"
#include "ckb_syscall_apis.h"
// clang-format on

#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,
};

const char *PERSONAL_SIGHASH_ALL = "ckb-tcob-sighash";
const char *PERSONAL_SIGHASH_ALL_ONLY = "ckb-tcob-sgohash";
const char *PERSONAL_OTX = "ckb-tcob-otxhash";

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);
}

typedef int (*load_function_t)(void *, uint64_t *, size_t, size_t, size_t);
#define BATCH_SIZE 1024

int streaming_hash(blake2b_state *ctx, size_t start, size_t total_len,
size_t index, size_t source, load_function_t f) {
int err = ERROR_GENERAL;
uint8_t temp[BATCH_SIZE];
uint64_t len = BATCH_SIZE;
size_t remaining_len = total_len;

int ret = f(temp, &len, start, index, source);
CHECK(ret);

uint64_t offset = (len > BATCH_SIZE) ? BATCH_SIZE : len;
if (remaining_len >= offset) {
blake2b_update(ctx, temp, offset);
remaining_len -= offset;
} else {
blake2b_update(ctx, temp, remaining_len);
return CKB_SUCCESS;
}

while (offset < len) {
uint64_t current_len = BATCH_SIZE;
ret = f(temp, &current_len, start + offset, index, source);
CHECK(err);
uint64_t current_read =
(current_len > BATCH_SIZE) ? BATCH_SIZE : current_len;
if (remaining_len >= current_read) {
blake2b_update(ctx, temp, current_read);
} else {
blake2b_update(ctx, temp, remaining_len);
return CKB_SUCCESS;
}
offset += current_read;
}

exit:
return err;
}

int ckb_hash_cell_data(blake2b_state *ctx, size_t index) {
size_t source = CKB_SOURCE_INPUT;
uint64_t cell_len = 0;
int err = ckb_load_cell_data(0, &cell_len, 0, index, source);
if (err) return err;
uint32_t cell_len2 = (uint32_t)cell_len;
// cobuild requires length = 4
blake2b_update(ctx, &cell_len2, sizeof(cell_len2));
return streaming_hash(ctx, 0, cell_len, index, source, ckb_load_cell_data);
}

int ckb_hash_witness(blake2b_state *ctx, size_t index) {
size_t source = CKB_SOURCE_INPUT;
uint64_t witness_len = 0;
int err = ckb_load_witness(0, &witness_len, 0, index, source);
if (err) return err;
// cobuild requires length = 4
uint32_t witness_len2 = (uint32_t)witness_len;
blake2b_update(ctx, &witness_len2, sizeof(witness_len2));
return streaming_hash(ctx, 0, witness_len, index, source, ckb_load_witness);
}

// 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);
CHECK2(witness_len > 0, ERROR_NONEMPTY_WITNESS);
}

exit:
return err;
}

int ckb_fetch_message(bool *has_message, size_t *index, size_t *start,
size_t *len) {
return 0;
}

static uint32_t read_from_witness(uintptr_t arg[], uint8_t *ptr, uint32_t len,
uint32_t offset) {
int err;
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 uint8_t g_witness_data_source[DEFAULT_DATA_SOURCE_LENGTH];
static int make_cobuild_witness(mol2_cursor_t *witness) {
int err = 0;
uint64_t witness_len = 0;
size_t source = CKB_SOURCE_GROUP_INPUT;
err = ckb_load_witness(NULL, &witness_len, 0, 0, source);
if (err != 0) {
return err;
}
mol2_cursor_t cur;

cur.offset = 0;
cur.size = (uint32_t)witness_len;

mol2_data_source_t *ptr = (mol2_data_source_t *)g_witness_data_source;

ptr->read = read_from_witness;
ptr->total_size = (uint32_t)witness_len;
// pass index and source as args
ptr->args[0] = 0;
ptr->args[1] = source;

ptr->cache_size = 0;
ptr->start_point = 0;
ptr->max_cache_size = MAX_CACHE_SIZE;
cur.data_source = ptr;

*witness = cur;

return 0;
}
30 changes: 30 additions & 0 deletions c/cobuild.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef __COBUILD_H__
#define __COBUILD_H__

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "blake2b_decl_only.h"

// return a blake2b instance with personalization for SighashAll
int new_sighash_all_blake2b(blake2b_state *S);

// return a blake2b instance with personalization for SighashAllOnly
int new_sighash_all_only_blake2b(blake2b_state *S);

// return a blake2b instance with personalization for OTX
int new_otx_blake2b(blake2b_state *S);

// hash whole cell data with source = INPUT
int ckb_hash_cell_data(blake2b_state *ctx, size_t index);
// hash whole witness with source = INPUT
int ckb_hash_witness(blake2b_state *ctx, size_t index);
int ckb_check_others_in_group();

// fetch message from input witness. *has_message = false if it doesn't exist.
// when *has_message = true, *start and *len together specify the slice in
// witness with *index.
int ckb_fetch_message(bool *has_message, size_t *index, size_t *start,
size_t *len);
#endif
1 change: 0 additions & 1 deletion tests/omni_lock_rust/Cargo.lock

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

4 changes: 0 additions & 4 deletions tests/omni_lock_rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,4 @@ 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"
Loading

0 comments on commit 261283c

Please sign in to comment.