#include "ckb_syscalls.h"
-#include "protocol.h"
diff --git a/.npm/package-lock.json b/.npm/package-lock.json index 4997d7c..715f9af 100644 --- a/.npm/package-lock.json +++ b/.npm/package-lock.json @@ -1,68 +1,97 @@ { + "name": ".npm", + "lockfileVersion": 3, "requires": true, - "lockfileVersion": 1, - "dependencies": { - "docco": { - "version": "0.8.0", - "resolved": "https://registry.npm.taobao.org/docco/download/docco-0.8.0.tgz", - "integrity": "sha1-7HFHD+UoCPTbuk+rcTgNzf6fU5Y=", - "requires": { - "commander": ">= 0.5.2", - "fs-extra": ">= 0.6.0", - "highlight.js": ">= 8.0.x", - "marked": ">= 0.2.7", - "underscore": ">= 1.0.0" + "packages": { + "": { + "dependencies": { + "docco": "=0.9.1" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/docco": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/docco/-/docco-0.9.1.tgz", + "integrity": "sha512-B1jUzcAc4AmicWUnmPTxUGM2lqJ11X4DiLUXyhzUVb7A1NNGTSNo3LtGzhHMyRAuJyxrHwHiOCDGuE/n9xRhmA==", + "dependencies": { + "commander": "~ 8.3.0", + "fs-extra": "~ 10.0.0", + "highlight.js": "~ 11.3.1", + "marked": "~ 4.0.3", + "underscore": "~ 1.13.1" + }, + "bin": { + "docco": "bin/docco" + }, + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, + "engines": { + "node": ">=12" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/highlight.js": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz", + "integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.nlark.com/commander/download/commander-7.2.0.tgz?cache=0&sync_timestamp=1622954303803&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcommander%2Fdownload%2Fcommander-7.2.0.tgz", - "integrity": "sha1-o2y1fQtQHOEI5NIFWaFQo5HZerc=" - }, - "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.nlark.com/fs-extra/download/fs-extra-10.0.0.tgz", - "integrity": "sha1-n/YbZV3eU/s0qC34S7IUzoAuF8E=", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.nlark.com/graceful-fs/download/graceful-fs-4.2.6.tgz", - "integrity": "sha1-/wQLKwhTsjw9MQJ1I3BvGIXXa+4=" - }, - "highlight.js": { - "version": "10.7.2", - "resolved": "https://registry.nlark.com/highlight.js/download/highlight.js-10.7.2.tgz", - "integrity": "sha1-iTGbhh7cZsSIVO0ebaIeqJ+Ec2A=" - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-6.1.0.tgz?cache=0&sync_timestamp=1604161876665&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-6.1.0.tgz", - "integrity": "sha1-vFWyY0eTxnnsZAMJTrE2mKbsCq4=", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "marked": { - "version": "2.1.1", - "resolved": "https://registry.nlark.com/marked/download/marked-2.1.1.tgz", - "integrity": "sha1-t8J/Ug/E3g3dBJ2bS+OwTgYxSSM=" - }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npm.taobao.org/underscore/download/underscore-1.13.1.tgz?cache=0&sync_timestamp=1618502952302&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funderscore%2Fdownload%2Funderscore-1.13.1.tgz", - "integrity": "sha1-DBxr0t9UtrafIxQGbWW2zeb8+dE=" - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-2.0.0.tgz?cache=0&sync_timestamp=1603180004159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-2.0.0.tgz", - "integrity": "sha1-daSYTv7cSwiXXFrrc/Uw0C3yVxc=" - } + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/marked": { + "version": "4.0.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz", + "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" } } } diff --git a/.npm/package.json b/.npm/package.json index e7c0a37..b8d378f 100644 --- a/.npm/package.json +++ b/.npm/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "docco": "=0.8.0" + "docco": "=0.9.1" } } diff --git a/build.rs b/build.rs index b83d6a4..cf2f36d 100644 --- a/build.rs +++ b/build.rs @@ -27,7 +27,7 @@ const BINARIES: &[(&str, &str)] = &[ ), ( "secp256k1_blake160_multisig_all", - "43400de165f0821abf63dcac299bbdf7fd73898675ee4ddb099b0a0d8db63bfb", + "50c8623ef5112510ccdf2d8e480d02d0de7288eb9968f8b019817340c3991145", ), ]; diff --git a/c/secp256k1_blake160_multisig_all.c b/c/secp256k1_blake160_multisig_all.c index f99a9c4..263bab8 100644 --- a/c/secp256k1_blake160_multisig_all.c +++ b/c/secp256k1_blake160_multisig_all.c @@ -285,8 +285,8 @@ int main() { // Verify threshold signatures, threshold is a uint8_t, at most it is // 255, meaning this array will definitely have a reasonable upper bound. // Also this code uses C99's new feature to allocate a variable length array. - uint8_t used_signatures[threshold]; - memset(used_signatures, 0, threshold); + uint8_t used_signatures[pubkeys_cnt]; + memset(used_signatures, 0, pubkeys_cnt); // We are using bitcoin's [secp256k1 library](https://github.com/bitcoin-core/secp256k1) // for signature verification here. To the best of our knowledge, this is an unmatched diff --git a/docs/c/dao.html b/docs/c/dao.html index 963e25f..5e25c1b 100644 --- a/docs/c/dao.html +++ b/docs/c/dao.html @@ -46,8 +46,8 @@
This file provides NervosDAO on chain script implementation. It is designed to @@ -62,16 +62,16 @@
Necessary headers. This script will need to perform syscalls to read current transaction structure, then parse WitnessArgs data structure in molecule format.
#include "ckb_syscalls.h"
-#include "protocol.h"
#include "ckb_syscalls.h"
+#include "protocol.h"
#define ERROR_UNKNOWN -1
-#define ERROR_WRONG_NUMBER_OF_ARGUMENTS -2
-#define ERROR_SYSCALL -4
-#define ERROR_BUFFER_NOT_ENOUGH -10
-#define ERROR_ENCODING -11
-#define ERROR_WITNESS_TOO_LONG -12
-#define ERROR_OVERFLOW -13
-#define ERROR_INVALID_WITHDRAW_BLOCK -14
-#define ERROR_INCORRECT_CAPACITY -15
-#define ERROR_INCORRECT_EPOCH -16
-#define ERROR_INCORRECT_SINCE -17
-#define ERROR_NEWLY_CREATED_CELL -19
-#define ERROR_INVALID_WITHDRAWING_CELL -20
-#define ERROR_SCRIPT_TOO_LONG -21
#define ERROR_UNKNOWN -1
+#define ERROR_WRONG_NUMBER_OF_ARGUMENTS -2
+#define ERROR_SYSCALL -4
+#define ERROR_BUFFER_NOT_ENOUGH -10
+#define ERROR_ENCODING -11
+#define ERROR_WITNESS_TOO_LONG -12
+#define ERROR_OVERFLOW -13
+#define ERROR_INVALID_WITHDRAW_BLOCK -14
+#define ERROR_INCORRECT_CAPACITY -15
+#define ERROR_INCORRECT_EPOCH -16
+#define ERROR_INCORRECT_SINCE -17
+#define ERROR_NEWLY_CREATED_CELL -19
+#define ERROR_INVALID_WITHDRAWING_CELL -20
+#define ERROR_SCRIPT_TOO_LONG -21
In case of missing deposit headers, load_dao_header_data would also return CKB_INDEX_OUT_OF_BOUND, so we cannot use CKB_INDEX_OUT_OF_BOUND as marker @@ -116,11 +116,11 @@
#define ERROR_MARKER_EXHAUSTED -30
+ #define ERROR_MARKER_EXHAUSTED -30
-#if ERROR_MARKER_EXHAUSTED == CKB_INDEX_OUT_OF_BOUND
-#error "Exhausted marker cannot be the same as CKB_INDEX_OUT_OF_BOUND!"
-#endif
+#if ERROR_MARKER_EXHAUSTED == CKB_INDEX_OUT_OF_BOUND
+#error "Exhausted marker cannot be the same as CKB_INDEX_OUT_OF_BOUND!"
+#endif
Common definitions here, one important limitation, is that this script only works with scripts and witnesses that are no larger than 32KB. We believe this should be enough @@ -137,11 +137,11 @@
#define HASH_SIZE 32
-#define HEADER_SIZE 4096
+ #define HASH_SIZE 32
+#define HEADER_SIZE 4096
/* 32 KB */
-#define MAX_WITNESS_SIZE 32768
-#define SCRIPT_SIZE 32768
+#define MAX_WITNESS_SIZE 32768
+#define SCRIPT_SIZE 32768
#define LOCK_PERIOD_EPOCHS 180
#define LOCK_PERIOD_EPOCHS 180
#define EPOCH_NUMBER_OFFSET 0
-#define EPOCH_NUMBER_BITS 24
-#define EPOCH_NUMBER_MASK ((1 << EPOCH_NUMBER_BITS) - 1)
-#define EPOCH_INDEX_OFFSET EPOCH_NUMBER_BITS
-#define EPOCH_INDEX_BITS 16
-#define EPOCH_INDEX_MASK ((1 << EPOCH_INDEX_BITS) - 1)
-#define EPOCH_LENGTH_OFFSET (EPOCH_NUMBER_BITS + EPOCH_INDEX_BITS)
-#define EPOCH_LENGTH_BITS 16
-#define EPOCH_LENGTH_MASK ((1 << EPOCH_LENGTH_BITS) - 1)
#define EPOCH_NUMBER_OFFSET 0
+#define EPOCH_NUMBER_BITS 24
+#define EPOCH_NUMBER_MASK ((1 << EPOCH_NUMBER_BITS) - 1)
+#define EPOCH_INDEX_OFFSET EPOCH_NUMBER_BITS
+#define EPOCH_INDEX_BITS 16
+#define EPOCH_INDEX_MASK ((1 << EPOCH_INDEX_BITS) - 1)
+#define EPOCH_LENGTH_OFFSET (EPOCH_NUMBER_BITS + EPOCH_INDEX_BITS)
+#define EPOCH_LENGTH_BITS 16
+#define EPOCH_LENGTH_MASK ((1 << EPOCH_LENGTH_BITS) - 1)
Fetches deposit header index. The index is kept in the witness of the same index as the input cell. The witness is first treated as a WitnessArgs object @@ -197,10 +197,10 @@
static int extract_deposit_header_index(size_t input_index, size_t *index) {
- int ret;
- uint64_t len = 0;
- unsigned char witness[MAX_WITNESS_SIZE];
+ static int extract_deposit_header_index(size_t input_index, size_t *index) {
+ int ret;
+ uint64_t len = 0;
+ unsigned char witness[MAX_WITNESS_SIZE];
len = MAX_WITNESS_SIZE;
ret = ckb_load_witness(witness, &len, 0, input_index, CKB_SOURCE_INPUT);
@@ -211,8 +211,8 @@ DAO
return ERROR_WITNESS_TOO_LONG;
}
- mol_seg_t witness_seg;
- witness_seg.ptr = (uint8_t *)witness;
+ mol_seg_t witness_seg;
+ witness_seg.ptr = (uint8_t *)witness;
witness_seg.size = len;
if (MolReader_WitnessArgs_verify(&witness_seg, false) != MOL_OK) {
@@ -225,20 +225,20 @@ DAO
-
- mol_seg_t type_seg = MolReader_WitnessArgs_get_input_type(&witness_seg);
+ mol_seg_t type_seg = MolReader_WitnessArgs_get_input_type(&witness_seg);
if (MolReader_BytesOpt_is_none(&type_seg)) {
return ERROR_ENCODING;
}
- mol_seg_t type_bytes_seg = MolReader_Bytes_raw_bytes(&type_seg);
+ mol_seg_t type_bytes_seg = MolReader_Bytes_raw_bytes(&type_seg);
if (type_bytes_seg.size != 8) {
return ERROR_ENCODING;
}
@@ -253,18 +253,18 @@ DAO
-
- static int extract_epoch_info(uint64_t epoch, int allow_zero_epoch_length,
- uint64_t *epoch_number, uint64_t *epoch_index,
- uint64_t *epoch_length) {
- uint64_t index = (epoch >> EPOCH_INDEX_OFFSET) & EPOCH_INDEX_MASK;
- uint64_t length = (epoch >> EPOCH_LENGTH_OFFSET) & EPOCH_LENGTH_MASK;
+ static int extract_epoch_info(uint64_t epoch, int allow_zero_epoch_length,
+ uint64_t *epoch_number, uint64_t *epoch_index,
+ uint64_t *epoch_length) {
+ uint64_t index = (epoch >> EPOCH_INDEX_OFFSET) & EPOCH_INDEX_MASK;
+ uint64_t length = (epoch >> EPOCH_LENGTH_OFFSET) & EPOCH_LENGTH_MASK;
if (length == 0) {
if (allow_zero_epoch_length) {
index = 0;
@@ -288,8 +288,8 @@ DAO
-
- ¶
+
+ §
All that information that will be needed from a block header by the NervosDAO
script.
@@ -297,12 +297,12 @@ DAO
typedef struct {
- uint64_t block_number;
- uint64_t epoch_number;
- uint64_t epoch_index;
- uint64_t epoch_length;
- uint8_t dao[32];
-} dao_header_data_t;
+ uint64_t block_number;
+ uint64_t epoch_number;
+ uint64_t epoch_index;
+ uint64_t epoch_length;
+ uint8_t dao[32];
+} dao_header_data_t;
@@ -310,18 +310,18 @@ DAO
-
- static int load_dao_header_data(size_t index, size_t source,
- dao_header_data_t *data) {
- uint8_t buffer[HEADER_SIZE];
- uint64_t len = HEADER_SIZE;
- int ret = ckb_load_header(buffer, &len, 0, index, source);
+ static int load_dao_header_data(size_t index, size_t source,
+ dao_header_data_t *data) {
+ uint8_t buffer[HEADER_SIZE];
+ uint64_t len = HEADER_SIZE;
+ int ret = ckb_load_header(buffer, &len, 0, index, source);
if (ret != CKB_SUCCESS) {
return ret;
}
@@ -335,29 +335,29 @@ DAO
-
- mol_seg_t header_seg;
- header_seg.ptr = (uint8_t *)buffer;
+ mol_seg_t header_seg;
+ header_seg.ptr = (uint8_t *)buffer;
header_seg.size = len;
if (MolReader_Header_verify(&header_seg, false) != MOL_OK) {
return ERROR_ENCODING;
}
- mol_seg_t raw_seg = MolReader_Header_get_raw(&header_seg);
- mol_seg_t dao_seg = MolReader_RawHeader_get_dao(&raw_seg);
- mol_seg_t epoch_seg = MolReader_RawHeader_get_epoch(&raw_seg);
- mol_seg_t block_number_seg = MolReader_RawHeader_get_number(&raw_seg);
+ mol_seg_t raw_seg = MolReader_Header_get_raw(&header_seg);
+ mol_seg_t dao_seg = MolReader_RawHeader_get_dao(&raw_seg);
+ mol_seg_t epoch_seg = MolReader_RawHeader_get_epoch(&raw_seg);
+ mol_seg_t block_number_seg = MolReader_RawHeader_get_number(&raw_seg);
- data->block_number = *((uint64_t *)block_number_seg.ptr);
+ data->block_number = *((uint64_t *)block_number_seg.ptr);
memcpy(data->dao, dao_seg.ptr, 32);
- return extract_epoch_info(*((uint64_t *)epoch_seg.ptr), 0,
+ return extract_epoch_info(*((uint64_t *)epoch_seg.ptr), 0,
&(data->epoch_number), &(data->epoch_index),
&(data->epoch_length));
}
@@ -368,8 +368,8 @@ DAO
-
- ¶
+
+ §
Validates an input cell is indeed deposited to NervosDAO in
deposited_block_number
, then calculates the capacity one can withdraw from
@@ -380,19 +380,19 @@
DAO
- static int calculate_dao_input_capacity(size_t input_index,
- uint64_t deposited_block_number,
- uint64_t original_capacity,
- uint64_t *calculated_capacity) {
- uint64_t len = 0;
- size_t deposit_index = 0;
+ static int calculate_dao_input_capacity(size_t input_index,
+ uint64_t deposited_block_number,
+ uint64_t original_capacity,
+ uint64_t *calculated_capacity) {
+ uint64_t len = 0;
+ size_t deposit_index = 0;
- int ret = extract_deposit_header_index(input_index, &deposit_index);
+ int ret = extract_deposit_header_index(input_index, &deposit_index);
if (ret != CKB_SUCCESS) {
return ret;
}
- dao_header_data_t deposit_data;
+ dao_header_data_t deposit_data;
ret =
load_dao_header_data(deposit_index, CKB_SOURCE_HEADER_DEP, &deposit_data);
if (ret != CKB_SUCCESS) {
@@ -405,8 +405,8 @@ DAO
-
- ¶
+
+ §
deposited_block_number must match actual deposited block
@@ -416,15 +416,15 @@ DAO
return ERROR_INVALID_WITHDRAW_BLOCK;
}
- dao_header_data_t withdraw_data;
+ dao_header_data_t withdraw_data;
ret = load_dao_header_data(input_index, CKB_SOURCE_INPUT, &withdraw_data);
if (ret != CKB_SUCCESS) {
return ret;
}
- uint64_t withdraw_fraction =
+ uint64_t withdraw_fraction =
withdraw_data.epoch_index * deposit_data.epoch_length;
- uint64_t deposit_fraction =
+ uint64_t deposit_fraction =
deposit_data.epoch_index * withdraw_data.epoch_length;
@@ -433,8 +433,8 @@ DAO
-
- ¶
+
+ §
Withdraw header must be after deposit header.
@@ -452,14 +452,14 @@ DAO
-
- uint64_t deposited_epochs =
+ uint64_t deposited_epochs =
withdraw_data.epoch_number - deposit_data.epoch_number;
@@ -468,8 +468,8 @@ DAO
-
- ¶
+
+ §
This is essentially a round-up operation. Suppose withdraw epoch is
a + b / c, deposit epoch is d + e / f, the deposited epochs will be:
@@ -488,7 +488,7 @@ DAO
if (withdraw_fraction > deposit_fraction) {
deposited_epochs++;
}
- uint64_t lock_epochs = (deposited_epochs + (LOCK_PERIOD_EPOCHS - 1)) /
+ uint64_t lock_epochs = (deposited_epochs + (LOCK_PERIOD_EPOCHS - 1)) /
LOCK_PERIOD_EPOCHS * LOCK_PERIOD_EPOCHS;
@@ -497,8 +497,8 @@ DAO
-
- ¶
+
+ §
Cell must at least be locked for one full lock period(180 epochs)
@@ -514,18 +514,18 @@ DAO
-
- ¶
+
+ §
Since actually just stores an epoch integer with a fraction part, it is
not necessary a valid epoch number with fraction.
- uint64_t minimal_since_epoch_number =
+ uint64_t minimal_since_epoch_number =
deposit_data.epoch_number + lock_epochs;
- uint64_t minimal_since_epoch_index = deposit_data.epoch_index;
- uint64_t minimal_since_epoch_length = deposit_data.epoch_length;
+ uint64_t minimal_since_epoch_index = deposit_data.epoch_index;
+ uint64_t minimal_since_epoch_length = deposit_data.epoch_length;
@@ -533,16 +533,16 @@ DAO
-
- uint64_t input_since = 0;
+ uint64_t input_since = 0;
len = 8;
- ret = ckb_load_input_by_field(((unsigned char *)&input_since), &len, 0,
+ ret = ckb_load_input_by_field(((unsigned char *)&input_since), &len, 0,
input_index, CKB_SOURCE_INPUT,
CKB_INPUT_FIELD_SINCE);
if (ret != CKB_SUCCESS) {
@@ -558,8 +558,8 @@ DAO
-
- ¶
+
+ §
NervosDAO requires DAO input field to have a since value represented
via absolute epoch number.
@@ -569,9 +569,9 @@ DAO
if (input_since >> 56 != 0x20) {
return ERROR_INCORRECT_SINCE;
}
- uint64_t input_since_epoch_number = 0;
- uint64_t input_since_epoch_index = 0;
- uint64_t input_since_epoch_length = 1;
+ uint64_t input_since_epoch_number = 0;
+ uint64_t input_since_epoch_index = 0;
+ uint64_t input_since_epoch_length = 1;
ret = extract_epoch_info(input_since, 1, &input_since_epoch_number,
&input_since_epoch_index, &input_since_epoch_length);
if (ret != CKB_SUCCESS) {
@@ -584,16 +584,16 @@ DAO
-
- uint64_t minimal_since_epoch_fraction =
+ uint64_t minimal_since_epoch_fraction =
minimal_since_epoch_index * input_since_epoch_length;
- uint64_t input_since_epoch_fraction =
+ uint64_t input_since_epoch_fraction =
input_since_epoch_index * minimal_since_epoch_length;
if ((input_since_epoch_number < minimal_since_epoch_number) ||
((input_since_epoch_number == minimal_since_epoch_number) &&
@@ -607,16 +607,16 @@ DAO
-
- ¶
+
+ §
Now we can calculate the maximum amount one can withdraw from this cell. Please
refer to Nervos DAO RFC for more details on the formula used here.
- uint64_t deposit_accumulate_rate = *((uint64_t *)(&deposit_data.dao[8]));
- uint64_t withdraw_accumulate_rate = *((uint64_t *)(&withdraw_data.dao[8]));
+ uint64_t deposit_accumulate_rate = *((uint64_t *)(&deposit_data.dao[8]));
+ uint64_t withdraw_accumulate_rate = *((uint64_t *)(&withdraw_data.dao[8]));
@@ -624,17 +624,17 @@ DAO
-
- ¶
+
+ §
Nervos DAO interest is only calculated on occupied capacity, which means all
capacities that are not used as storage cost in a cell.
- uint64_t occupied_capacity = 0;
+ uint64_t occupied_capacity = 0;
len = 8;
- ret = ckb_load_cell_by_field(((unsigned char *)&occupied_capacity), &len, 0,
+ ret = ckb_load_cell_by_field(((unsigned char *)&occupied_capacity), &len, 0,
input_index, CKB_SOURCE_INPUT,
CKB_CELL_FIELD_OCCUPIED_CAPACITY);
if (ret != CKB_SUCCESS) {
@@ -650,14 +650,14 @@ DAO
-
- uint64_t counted_capacity = 0;
+ uint64_t counted_capacity = 0;
if (__builtin_usubl_overflow(original_capacity, occupied_capacity,
&counted_capacity)) {
return ERROR_OVERFLOW;
@@ -667,9 +667,9 @@ DAO
((__int128)withdraw_accumulate_rate) /
((__int128)deposit_accumulate_rate);
- uint64_t withdraw_capacity = 0;
+ uint64_t withdraw_capacity = 0;
if (__builtin_uaddl_overflow(occupied_capacity,
- (uint64_t)withdraw_counted_capacity,
+ (uint64_t)withdraw_counted_capacity,
&withdraw_capacity)) {
return ERROR_OVERFLOW;
}
@@ -684,8 +684,8 @@ DAO
-
- ¶
+
+ §
In the phase 1 of NervosDAO script, we will consume a deposited cell, and
create a withdrawing cell. The withdrawing cell must be put in the same index
@@ -704,10 +704,10 @@
DAO
- static int validate_withdrawing_cell(size_t index, uint64_t input_capacity,
- unsigned char *dao_script_hash) {
- unsigned char hash1[HASH_SIZE];
- uint64_t len = HASH_SIZE;
+ static int validate_withdrawing_cell(size_t index, uint64_t input_capacity,
+ unsigned char *dao_script_hash) {
+ unsigned char hash1[HASH_SIZE];
+ uint64_t len = HASH_SIZE;
@@ -715,15 +715,15 @@ DAO
-
len = HASH_SIZE;
- int ret = ckb_load_cell_by_field(hash1, &len, 0, index, CKB_SOURCE_OUTPUT,
+ int ret = ckb_load_cell_by_field(hash1, &len, 0, index, CKB_SOURCE_OUTPUT,
CKB_CELL_FIELD_TYPE_HASH);
if (ret != CKB_SUCCESS) {
return ret;
@@ -741,17 +741,17 @@ DAO
-
- uint64_t output_capacity = 0;
+ uint64_t output_capacity = 0;
len = 8;
ret =
- ckb_load_cell_by_field((unsigned char *)&output_capacity, &len, 0, index,
+ ckb_load_cell_by_field((unsigned char *)&output_capacity, &len, 0, index,
CKB_SOURCE_OUTPUT, CKB_CELL_FIELD_CAPACITY);
if (ret != CKB_SUCCESS) {
return ret;
@@ -769,21 +769,21 @@ DAO
-
- dao_header_data_t deposit_header;
+ dao_header_data_t deposit_header;
ret = load_dao_header_data(index, CKB_SOURCE_INPUT, &deposit_header);
if (ret != CKB_SUCCESS) {
return ret;
}
- uint64_t stored_block_number = 0;
+ uint64_t stored_block_number = 0;
len = 8;
- ret = ckb_load_cell_data((unsigned char *)&stored_block_number, &len, 0,
+ ret = ckb_load_cell_data((unsigned char *)&stored_block_number, &len, 0,
index, CKB_SOURCE_OUTPUT);
if (ret != CKB_SUCCESS) {
return ret;
@@ -797,13 +797,13 @@ DAO
return CKB_SUCCESS;
}
-static int validate_input(size_t index, uint64_t *input_capacities,
- uint64_t *output_withdrawing,
- unsigned char *script_hash) {
- int dao_input = 0;
- uint64_t capacity = 0;
- uint64_t len = 8;
- int ret = ckb_load_cell_by_field(((unsigned char *)&capacity), &len, 0, index,
+static int validate_input(size_t index, uint64_t *input_capacities,
+ uint64_t *output_withdrawing,
+ unsigned char *script_hash) {
+ int dao_input = 0;
+ uint64_t capacity = 0;
+ uint64_t len = 8;
+ int ret = ckb_load_cell_by_field(((unsigned char *)&capacity), &len, 0, index,
CKB_SOURCE_INPUT, CKB_CELL_FIELD_CAPACITY);
if (ret == CKB_INDEX_OUT_OF_BOUND) {
return ERROR_MARKER_EXHAUSTED;
@@ -811,7 +811,7 @@ DAO
if (len != 8) {
return ERROR_SYSCALL;
}
- unsigned char current_script_hash[HASH_SIZE];
+ unsigned char current_script_hash[HASH_SIZE];
len = HASH_SIZE;
ret = ckb_load_cell_by_field(current_script_hash, &len, 0, index,
CKB_SOURCE_INPUT, CKB_CELL_FIELD_TYPE_HASH);
@@ -822,8 +822,8 @@ DAO
-
- ¶
+
+ §
When an input cell has the same type script hash as current running
we know we are dealing with a script using NervosDAO script.
@@ -846,8 +846,8 @@ DAO
-
- ¶
+
+ §
Normal input, use its own capacity
@@ -865,8 +865,8 @@ DAO
-
- ¶
+
+ §
In a Nervos DAO transaction, we might have 2 types of input cells using
Nervos DAO type script:
@@ -883,9 +883,9 @@ DAO
- uint64_t block_number = 0;
+ uint64_t block_number = 0;
len = 8;
- ret = ckb_load_cell_data((unsigned char *)&block_number, &len, 0, index,
+ ret = ckb_load_cell_data((unsigned char *)&block_number, &len, 0, index,
CKB_SOURCE_INPUT);
if (ret != CKB_SUCCESS) {
return ret;
@@ -902,15 +902,15 @@ DAO
-
- ¶
+
+ §
For a withdrawing cell, we can start calculate the maximum capacity
that one can withdraw from it.
- uint64_t dao_capacity = 0;
+ uint64_t dao_capacity = 0;
ret = calculate_dao_input_capacity(index, block_number, capacity,
&dao_capacity);
if (ret != CKB_SUCCESS) {
@@ -923,8 +923,8 @@ DAO
-
- ¶
+
+ §
Like any serious smart contracts, we will perform overflow checks here.
@@ -942,8 +942,8 @@ DAO
-
- ¶
+
+ §
For a deposited cell, we only need to check that a withdrawing cell for
current one is generated. For simplicity, we are limiting the code so
@@ -964,8 +964,8 @@
DAO
-
- ¶
+
+ §
Note that validate_withdrawing_cell
above already verifies that an
output cell for the current input cell at the same location exists.
@@ -980,8 +980,8 @@ DAO
-
- ¶
+
+ §
Like any serious smart contracts, we will perform overflow checks here.
@@ -997,12 +997,12 @@ DAO
return 0;
}
-static int validate_output(size_t index, uint64_t *output_capacities,
- uint64_t output_withdrawing,
- unsigned char *script_hash) {
- uint64_t capacity = 0;
- uint64_t len = 8;
- int ret = ckb_load_cell_by_field(((unsigned char *)&capacity), &len, 0, index,
+static int validate_output(size_t index, uint64_t *output_capacities,
+ uint64_t output_withdrawing,
+ unsigned char *script_hash) {
+ uint64_t capacity = 0;
+ uint64_t len = 8;
+ int ret = ckb_load_cell_by_field(((unsigned char *)&capacity), &len, 0, index,
CKB_SOURCE_OUTPUT, CKB_CELL_FIELD_CAPACITY);
if (ret == CKB_INDEX_OUT_OF_BOUND) {
return ERROR_MARKER_EXHAUSTED;
@@ -1020,8 +1020,8 @@ DAO
-
- ¶
+
+ §
Like any serious smart contracts, we will perform overflow checks here.
@@ -1032,7 +1032,7 @@ DAO
return ERROR_OVERFLOW;
}
- unsigned char current_script_hash[HASH_SIZE];
+ unsigned char current_script_hash[HASH_SIZE];
len = HASH_SIZE;
ret = ckb_load_cell_by_field(current_script_hash, &len, 0, index,
CKB_SOURCE_OUTPUT, CKB_CELL_FIELD_TYPE_HASH);
@@ -1045,8 +1045,8 @@ DAO
-
- ¶
+
+ §
Similarly to input, we also need to check if we are creating a
deposited cell, or a withdrawing cell here. This can be easily determined
@@ -1061,9 +1061,9 @@
DAO
if (output_withdrawing == 0) {
- uint64_t block_number = 0;
+ uint64_t block_number = 0;
len = 8;
- ret = ckb_load_cell_data((unsigned char *)&block_number, &len, 0, index,
+ ret = ckb_load_cell_data((unsigned char *)&block_number, &len, 0, index,
CKB_SOURCE_OUTPUT);
if (ret != CKB_SUCCESS) {
return ret;
@@ -1080,14 +1080,14 @@ DAO
}
-int main() {
- int ret;
- unsigned char script_hash[HASH_SIZE];
- unsigned char script[SCRIPT_SIZE];
- uint64_t len = 0;
- mol_seg_t script_seg;
- mol_seg_t args_seg;
- mol_seg_t bytes_seg;
+int main() {
+ int ret;
+ unsigned char script_hash[HASH_SIZE];
+ unsigned char script[SCRIPT_SIZE];
+ uint64_t len = 0;
+ mol_seg_t script_seg;
+ mol_seg_t args_seg;
+ mol_seg_t bytes_seg;
@@ -1095,8 +1095,8 @@ DAO
-
- ¶
+
+ §
NervosDAO script requires script args part to be empty, this way we can ensure
that all DAO related scripts in a transaction is mapped to the same group, and
@@ -1112,7 +1112,7 @@
DAO
if (len > SCRIPT_SIZE) {
return ERROR_SCRIPT_TOO_LONG;
}
- script_seg.ptr = (uint8_t *)script;
+ script_seg.ptr = (uint8_t *)script;
script_seg.size = len;
if (MolReader_Script_verify(&script_seg, false) != MOL_OK) {
return ERROR_ENCODING;
@@ -1129,8 +1129,8 @@ DAO
-
- ¶
+
+ §
Load current script hash. Unlike a lock script which only cares for cells
using its own lock script. The NervosDAO script here will need to loop
@@ -1155,8 +1155,8 @@
DAO
-
- ¶
+
+ §
First, we will need to loop against all input cells in current transaction.
For a normal transaction, we will just add up its own capacity. For a
@@ -1173,8 +1173,8 @@
DAO
-
- ¶
+
+ §
Also let’s loop through all output cells, and calculate the sum of output
capacities here.
@@ -1182,13 +1182,13 @@ DAO
- size_t index = 0;
- uint64_t input_capacities = 0;
- uint64_t output_capacities = 0;
- uint64_t output_withdrawing = 0;
+ size_t index = 0;
+ uint64_t input_capacities = 0;
+ uint64_t output_capacities = 0;
+ uint64_t output_withdrawing = 0;
- uint64_t input_exhausted = 0;
- uint64_t output_exhausted = 0;
+ uint64_t input_exhausted = 0;
+ uint64_t output_exhausted = 0;
while (!(input_exhausted && output_exhausted)) {
@@ -1197,8 +1197,8 @@ DAO
-
- ¶
+
+ §
Reset the flag to ensure that it does not retain the value from the last iteration when
inputs have been exhausted.
@@ -1234,8 +1234,8 @@ DAO
-
- ¶
+
+ §
The final thing we need to check here, is that the sum of capacities in output
cells, cannot exceed the sum of capacities in all input cells with Nervos DAO
diff --git a/docs/c/secp256k1_blake160_multisig_all.html b/docs/c/secp256k1_blake160_multisig_all.html
index 9bd99f4..b5b11c7 100644
--- a/docs/c/secp256k1_blake160_multisig_all.html
+++ b/docs/c/secp256k1_blake160_multisig_all.html
@@ -46,8 +46,8 @@
-
- ¶
+
+ §
secp256k1-blake160-multisig-all
This is a lock script that serves multiple purposes:
@@ -86,8 +86,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
First we will need to include a few headers here, for legacy reasons, this repository
ships with those headers. We are now maintaining a new repository
@@ -96,11 +96,11 @@
secp256k1-blake160-multisig-all
- #include "blake2b.h"
-#include "ckb_syscalls.h"
-#include "common.h"
-#include "protocol.h"
-#include "secp256k1_helper.h"
+ #include "blake2b.h"
+#include "ckb_syscalls.h"
+#include "common.h"
+#include "protocol.h"
+#include "secp256k1_helper.h"
@@ -108,17 +108,17 @@ secp256k1-blake160-multisig-all
-
- #define ERROR_INVALID_RESERVE_FIELD -41
-#define ERROR_INVALID_PUBKEYS_CNT -42
-#define ERROR_INVALID_THRESHOLD -43
-#define ERROR_INVALID_REQUIRE_FIRST_N -44
+ #define ERROR_INVALID_RESERVE_FIELD -41
+#define ERROR_INVALID_PUBKEYS_CNT -42
+#define ERROR_INVALID_THRESHOLD -43
+#define ERROR_INVALID_REQUIRE_FIRST_N -44
@@ -126,15 +126,15 @@ secp256k1-blake160-multisig-all
-
- #define ERROR_MULTSIG_SCRIPT_HASH -51
-#define ERROR_VERIFICATION -52
+ #define ERROR_MULTSIG_SCRIPT_HASH -51
+#define ERROR_VERIFICATION -52
@@ -142,8 +142,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Common definitions here, one important limitation, is that this lock script only works
with scripts and witnesses that are no larger than 32KB. We believe this should be enough
@@ -153,16 +153,16 @@
secp256k1-blake160-multisig-all
- #define BLAKE2B_BLOCK_SIZE 32
-#define BLAKE160_SIZE 20
-#define PUBKEY_SIZE 33
-#define TEMP_SIZE 32768
-#define RECID_INDEX 64
+ #define BLAKE2B_BLOCK_SIZE 32
+#define BLAKE160_SIZE 20
+#define PUBKEY_SIZE 33
+#define TEMP_SIZE 32768
+#define RECID_INDEX 64
/* 32 KB */
-#define MAX_WITNESS_SIZE 32768
-#define MAX_SCRIPT_SIZE 32768
-#define SIGNATURE_SIZE 65
-#define FLAGS_SIZE 4
+#define MAX_WITNESS_SIZE 32768
+#define MAX_SCRIPT_SIZE 32768
+#define SIGNATURE_SIZE 65
+#define FLAGS_SIZE 4
@@ -170,16 +170,16 @@ secp256k1-blake160-multisig-all
-
- #if (MAX_WITNESS_SIZE > TEMP_SIZE) || (MAX_SCRIPT_SIZE > TEMP_SIZE)
-#error "Temp buffer is not big enough!"
-#endif
+ #if (MAX_WITNESS_SIZE > TEMP_SIZE) || (MAX_SCRIPT_SIZE > TEMP_SIZE)
+#error "Temp buffer is not big enough!"
+#endif
@@ -187,8 +187,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
To use this script, the script args part must contain the blake160 hash of the
multisig_script
part mentioned above. The blake160 hash is calculated as the
@@ -199,10 +199,10 @@
secp256k1-blake160-multisig-all
- int main() {
- int ret;
- uint64_t len;
- unsigned char temp[TEMP_SIZE];
+ int main() {
+ int ret;
+ uint64_t len;
+ unsigned char temp[TEMP_SIZE];
@@ -210,15 +210,15 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
First let’s load and extract script args part, which is also the blake160 hash of public
key from current running script.
- unsigned char script[MAX_SCRIPT_SIZE];
+ unsigned char script[MAX_SCRIPT_SIZE];
len = MAX_SCRIPT_SIZE;
ret = ckb_load_script(script, &len, 0);
if (ret != CKB_SUCCESS) {
@@ -227,16 +227,16 @@ secp256k1-blake160-multisig-all
if (len > MAX_SCRIPT_SIZE) {
return ERROR_SCRIPT_TOO_LONG;
}
- mol_seg_t script_seg;
- script_seg.ptr = (uint8_t *)script;
+ mol_seg_t script_seg;
+ script_seg.ptr = (uint8_t *)script;
script_seg.size = len;
if (MolReader_Script_verify(&script_seg, false) != MOL_OK) {
return ERROR_ENCODING;
}
- mol_seg_t args_seg = MolReader_Script_get_args(&script_seg);
- mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg);
+ mol_seg_t args_seg = MolReader_Script_get_args(&script_seg);
+ mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg);
@@ -244,8 +244,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
The script args part should either be 20 bytes(containing only the blake160 hash),
or 28 bytes(containing blake160 hash and since value).
@@ -253,7 +253,7 @@ secp256k1-blake160-multisig-all
if (args_bytes_seg.size != BLAKE160_SIZE &&
- args_bytes_seg.size != BLAKE160_SIZE + sizeof(uint64_t)) {
+ args_bytes_seg.size != BLAKE160_SIZE + sizeof(uint64_t)) {
return ERROR_ARGUMENTS_LEN;
}
@@ -263,16 +263,16 @@ secp256k1-blake160-multisig-all
-
- uint64_t since = 0;
- if (args_bytes_seg.size == BLAKE160_SIZE + sizeof(uint64_t)) {
- since = *(uint64_t *)&args_bytes_seg.ptr[BLAKE160_SIZE];
+ uint64_t since = 0;
+ if (args_bytes_seg.size == BLAKE160_SIZE + sizeof(uint64_t)) {
+ since = *(uint64_t *)&args_bytes_seg.ptr[BLAKE160_SIZE];
}
@@ -281,16 +281,16 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Load the first witness, or the witness of the same index as the first input using
current script.
- unsigned char witness[MAX_WITNESS_SIZE];
- uint64_t witness_len = MAX_WITNESS_SIZE;
+ unsigned char witness[MAX_WITNESS_SIZE];
+ uint64_t witness_len = MAX_WITNESS_SIZE;
ret = ckb_load_witness(witness, &witness_len, 0, 0, CKB_SOURCE_GROUP_INPUT);
if (ret != CKB_SUCCESS) {
return ERROR_SYSCALL;
@@ -305,15 +305,15 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
We will treat the first witness as WitnessArgs object, and extract the lock field
from the object.
- mol_seg_t lock_bytes_seg;
+ mol_seg_t lock_bytes_seg;
ret = extract_witness_lock(witness, witness_len, &lock_bytes_seg);
if (ret != CKB_SUCCESS) {
return ret;
@@ -329,8 +329,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
This is more of a safe guard, since lock is a field in witness, it
cannot exceed the maximum size of the enclosing witness, this way
@@ -349,15 +349,15 @@
secp256k1-blake160-multisig-all
-
- unsigned char lock_bytes[lock_bytes_seg.size];
- uint64_t lock_bytes_len = lock_bytes_seg.size;
+ unsigned char lock_bytes[lock_bytes_seg.size];
+ uint64_t lock_bytes_len = lock_bytes_seg.size;
memcpy(lock_bytes, lock_bytes_seg.ptr, lock_bytes_len);
@@ -366,17 +366,17 @@ secp256k1-blake160-multisig-all
-
- uint8_t pubkeys_cnt = lock_bytes[3];
- uint8_t threshold = lock_bytes[2];
- uint8_t require_first_n = lock_bytes[1];
- uint8_t reserved_field = lock_bytes[0];
+ uint8_t pubkeys_cnt = lock_bytes[3];
+ uint8_t threshold = lock_bytes[2];
+ uint8_t require_first_n = lock_bytes[1];
+ uint8_t reserved_field = lock_bytes[0];
if (reserved_field != 0) {
return ERROR_INVALID_RESERVE_FIELD;
}
@@ -399,17 +399,17 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Based on the number of public keys and thresholds, we can calculate
the required length of the lock field.
- size_t multisig_script_len = FLAGS_SIZE + BLAKE160_SIZE * pubkeys_cnt;
- size_t signatures_len = SIGNATURE_SIZE * threshold;
- size_t required_lock_len = multisig_script_len + signatures_len;
+ size_t multisig_script_len = FLAGS_SIZE + BLAKE160_SIZE * pubkeys_cnt;
+ size_t signatures_len = SIGNATURE_SIZE * threshold;
+ size_t required_lock_len = multisig_script_len + signatures_len;
if (lock_bytes_len != required_lock_len) {
return ERROR_WITNESS_SIZE;
}
@@ -420,8 +420,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Perform hash check of the multisig_script
part, notice the signature part
is not included here.
@@ -443,8 +443,8 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Check lock period logic, we have prepared a handy utility function for this.
@@ -461,14 +461,14 @@ secp256k1-blake160-multisig-all
-
- unsigned char tx_hash[BLAKE2B_BLOCK_SIZE];
+ unsigned char tx_hash[BLAKE2B_BLOCK_SIZE];
len = BLAKE2B_BLOCK_SIZE;
ret = ckb_load_tx_hash(tx_hash, &len, 0);
if (ret != CKB_SUCCESS) {
@@ -484,14 +484,14 @@ secp256k1-blake160-multisig-all
-
- memset((void *)(lock_bytes_seg.ptr + multisig_script_len), 0, signatures_len);
+ memset((void *)(lock_bytes_seg.ptr + multisig_script_len), 0, signatures_len);
@@ -499,15 +499,15 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Here we start to prepare the message used in signature verification. First, let’s
hash the just loaded transaction hash.
- unsigned char message[BLAKE2B_BLOCK_SIZE];
+ unsigned char message[BLAKE2B_BLOCK_SIZE];
blake2b_init(&blake2b_ctx, BLAKE2B_BLOCK_SIZE);
blake2b_update(&blake2b_ctx, tx_hash, BLAKE2B_BLOCK_SIZE);
@@ -517,15 +517,15 @@ secp256k1-blake160-multisig-all
-
- ¶
+
+ §
Before hashing each witness, we need to hash the witness length first as a 64-bit
unsigned little endian integer.
- blake2b_update(&blake2b_ctx, (char *)&witness_len, sizeof(uint64_t));
+ blake2b_update(&blake2b_ctx, (char *)&witness_len, sizeof(uint64_t));
@@ -533,8 +533,8 @@ secp256k1-blake160-multisig-all