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 @@
  • -
    - +
    + §

    DAO

    This file provides NervosDAO on chain script implementation. It is designed to @@ -62,16 +62,16 @@

    DAO

  • -
    - +
    + §

    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"
  • @@ -79,27 +79,27 @@

    DAO

  • -
    - +
    + §

    Error definitions

    -
    #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
  • @@ -107,8 +107,8 @@

    DAO

  • -
    - +
    + §

    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 @@

    DAO

    -
    #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
  • @@ -128,8 +128,8 @@

    DAO

  • -
    - +
    + §

    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 @@

    DAO

    -
    #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
  • @@ -149,14 +149,14 @@

    DAO

  • -
    - +
    + §

    One lock period of NervosDAO is set as 180 epochs, which is roughly 30 days.

    -
    #define LOCK_PERIOD_EPOCHS 180
    +
    #define LOCK_PERIOD_EPOCHS 180
  • @@ -164,22 +164,22 @@

    DAO

  • -
    - +
    + §

    Common definitions to parse epoch value in block headers.

    -
    #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)
  • @@ -187,8 +187,8 @@

    DAO

  • -
    - +
    + §

    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 @@

    DAO

    -
    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

  • -
    - +
    + §

    Load input_type

    -
      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

  • -
    - +
    + §

    Parses epoch info from the epoch field in block header.

    -
    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

  • -
    - +
    + §

    Load a block header and extract all the useful data.

    -
    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

  • -
    - +
    + §

    The header is also serialized in molecule format.

    -
      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

  • -
    - +
    + §

    Full deposited epochs

    -
      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

  • -
    - +
    + §

    Loads since value from current input to make sure correct lock period is set.

    -
      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

  • -
    - +
    + §

    Validates that correct since value is set to ensure 180 epochs lock period.

    -
      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

  • -
    - +
    + §

    Like any serious smart contracts, we will perform overflow checks here.

    -
      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

  • -
    - +
    + §

    Check type script

      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

  • -
    - +
    + §

    Check capacity

    -
      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

  • -
    - +
    + §

    Check cell data

    -
      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

  • -
    - +
    + §

    Script args validation errors

    -
    #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

  • -
    - +
    + §

    Multi-sigining validation errors

    -
    #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

  • -
    - +
    + §

    Compile-time guard against buffer abuse

    -
    #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

  • -
    - +
    + §

    Extract optional since value.

    -
      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

  • -
    - +
    + §

    Keep the full lock field somewhere, since later we will modify this field in place.

    -
      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

  • -
    - +
    + §

    Extract multisig script flags.

    -
      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

  • -
    - +
    + §

    Load the current transaction hash.

    -
      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

  • -
    - +
    + §

    Erase the signature part to all zeros, so we can prepare the sining message.

    -
      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

  • -
    - +
    + §

    Like shown above, we will fill the signature section with all 0, then used the modified first witness here as the value to hash.

    @@ -549,15 +549,15 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Let’s loop and hash all witnesses with the same indices as the remaining input cells using current running lock script.

    -
      size_t i = 1;
    +            
      size_t i = 1;
       while (1) {
         len = MAX_WITNESS_SIZE;
    @@ -567,8 +567,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Using CKB_SOURCE_GROUP_INPUT as the source value provides us with a quick way to loop through all input cells using current running lock script. We don’t have to @@ -593,15 +593,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 *)&len, sizeof(uint64_t));
    +            
        blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t));
         blake2b_update(&blake2b_ctx, temp, len);
         i += 1;
       }
    @@ -612,8 +612,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    For safety consideration, this lock script will also hash and guard all witnesses that have index values equal to or larger than the number of input cells. It assumes all @@ -634,8 +634,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Here we are guarding input cells with any arbitrary lock script, hence we are using the plain CKB_SOURCE_INPUT source to loop all witnesses.

    @@ -659,15 +659,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 *)&len, sizeof(uint64_t));
    +            
        blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t));
         blake2b_update(&blake2b_ctx, temp, len);
         i += 1;
       }
    @@ -678,8 +678,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Now the message preparation is completed.

    @@ -693,8 +693,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Verify threshold signatures, threshold is a uint8_t, at most it is 255, meaning this array will definitely have a reasonable upper bound. @@ -702,8 +702,8 @@

    secp256k1-blake160-multisig-all

    -
      uint8_t used_signatures[threshold];
    -  memset(used_signatures, 0, threshold);
    +
      uint8_t used_signatures[pubkeys_cnt];
    +  memset(used_signatures, 0, pubkeys_cnt);
  • @@ -711,8 +711,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    We are using bitcoin’s secp256k1 library for signature verification here. To the best of our knowledge, this is an unmatched @@ -723,7 +723,7 @@

    secp256k1-blake160-multisig-all

      secp256k1_context context;
    -  uint8_t secp_data[CKB_SECP256K1_DATA_SIZE];
    +  uint8_t secp_data[CKB_SECP256K1_DATA_SIZE];
       ret = ckb_secp256k1_custom_verify_only_initialize(&context, secp_data);
       if (ret != 0) {
         return ret;
    @@ -735,14 +735,14 @@ 

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    We will perform threshold number of signature verifications here.

    -
      for (size_t i = 0; i < threshold; i++) {
    +
      for (size_t i = 0; i < threshold; i++) {
  • @@ -750,15 +750,15 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Load signature

        secp256k1_ecdsa_recoverable_signature signature;
    -    size_t signature_offset = multisig_script_len + i * SIGNATURE_SIZE;
    +    size_t signature_offset = multisig_script_len + i * SIGNATURE_SIZE;
         if (secp256k1_ecdsa_recoverable_signature_parse_compact(
                 &context, &signature, &lock_bytes[signature_offset],
                 lock_bytes[signature_offset + RECID_INDEX]) == 0) {
    @@ -771,8 +771,8 @@ 

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    verifiy signature and Recover pubkey

    @@ -789,20 +789,20 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Calculate the blake160 hash of the derived public key

    -
        size_t pubkey_size = PUBKEY_SIZE;
    +            
        size_t pubkey_size = PUBKEY_SIZE;
         if (secp256k1_ec_pubkey_serialize(&context, temp, &pubkey_size, &pubkey,
                                           SECP256K1_EC_COMPRESSED) != 1) {
           return ERROR_SECP_SERIALIZE_PUBKEY;
         }
     
    -    unsigned char calculated_pubkey_hash[BLAKE2B_BLOCK_SIZE];
    +    unsigned char calculated_pubkey_hash[BLAKE2B_BLOCK_SIZE];
         blake2b_state blake2b_ctx;
         blake2b_init(&blake2b_ctx, BLAKE2B_BLOCK_SIZE);
         blake2b_update(&blake2b_ctx, temp, PUBKEY_SIZE);
    @@ -814,15 +814,15 @@ 

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    Check if this signature is signed with one of the provided public key.

    -
        uint8_t matched = 0;
    -    for (size_t i = 0; i < pubkeys_cnt; i++) {
    +            
        uint8_t matched = 0;
    +    for (size_t i = 0; i < pubkeys_cnt; i++) {
           if (used_signatures[i] == 1) {
             continue;
           }
    @@ -841,8 +841,8 @@ 

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    If the signature doesn’t match any of the provided public key, the script will exit with an error.

    @@ -860,8 +860,8 @@

    secp256k1-blake160-multisig-all

  • -
    - +
    + §

    The above scheme just ensures that a threshold number of signatures have successfully been verified, and they all come from the provided public keys. @@ -872,7 +872,7 @@

    secp256k1-blake160-multisig-all

    -
      for (size_t i = 0; i < require_first_n; i++) {
    +            
      for (size_t i = 0; i < require_first_n; i++) {
         if (used_signatures[i] != 1) {
           return ERROR_VERIFICATION;
         }
    diff --git a/docs/c/secp256k1_blake160_sighash_all.html b/docs/c/secp256k1_blake160_sighash_all.html
    index 152e16a..8cc0716 100644
    --- a/docs/c/secp256k1_blake160_sighash_all.html
    +++ b/docs/c/secp256k1_blake160_sighash_all.html
    @@ -46,8 +46,8 @@
             
  • -
    - +
    + §

    secp256k1-blake160-sighash-all

    This is a lock script code using the same secp256k1 signature verification algorithm @@ -92,8 +92,8 @@

    secp256k1-blake160-sighash-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 @@ -102,11 +102,11 @@

    secp256k1-blake160-sighash-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"
  • @@ -114,8 +114,8 @@

    secp256k1-blake160-sighash-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 @@ -125,15 +125,15 @@

    secp256k1-blake160-sighash-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 SCRIPT_SIZE 32768
    -#define SIGNATURE_SIZE 65
    +#define MAX_WITNESS_SIZE 32768 +#define SCRIPT_SIZE 32768 +#define SIGNATURE_SIZE 65
  • @@ -141,16 +141,16 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Compile-time guard against buffer abuse

    -
    #if (MAX_WITNESS_SIZE > TEMP_SIZE) || (SCRIPT_SIZE > TEMP_SIZE)
    -#error "Temp buffer is not big enough!"
    -#endif
    +
    #if (MAX_WITNESS_SIZE > TEMP_SIZE) || (SCRIPT_SIZE > TEMP_SIZE)
    +#error "Temp buffer is not big enough!"
    +#endif
  • @@ -158,8 +158,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    To use this script, some conventions are required:

    The script args part should contain the blake160 hash of a public key, which is the @@ -172,11 +172,11 @@

    secp256k1-blake160-sighash-all

    -
    int main() {
    -  int ret;
    -  uint64_t len = 0;
    -  unsigned char temp[TEMP_SIZE];
    -  unsigned char lock_bytes[SIGNATURE_SIZE];
    +
    int main() {
    +  int ret;
    +  uint64_t len = 0;
    +  unsigned char temp[TEMP_SIZE];
    +  unsigned char lock_bytes[SIGNATURE_SIZE];
  • @@ -184,15 +184,15 @@

    secp256k1-blake160-sighash-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[SCRIPT_SIZE];
    +            
      unsigned char script[SCRIPT_SIZE];
       len = SCRIPT_SIZE;
       ret = ckb_load_script(script, &len, 0);
       if (ret != CKB_SUCCESS) {
    @@ -201,16 +201,16 @@ 

    secp256k1-blake160-sighash-all

    if (len > 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); if (args_bytes_seg.size != BLAKE160_SIZE) { return ERROR_ARGUMENTS_LEN; }
    @@ -221,15 +221,15 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Load the first witness, or the witness of the same index as the first input using current script.

    -
      uint64_t witness_len = MAX_WITNESS_SIZE;
    +            
      uint64_t witness_len = MAX_WITNESS_SIZE;
       ret = ckb_load_witness(temp, &witness_len, 0, 0, CKB_SOURCE_GROUP_INPUT);
       if (ret != CKB_SUCCESS) {
         return ERROR_SYSCALL;
    @@ -245,15 +245,15 @@ 

    secp256k1-blake160-sighash-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(temp, witness_len, &lock_bytes_seg);
       if (ret != 0) {
         return ERROR_ENCODING;
    @@ -265,8 +265,8 @@ 

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    The lock field must be 65 byte long to represent a (possibly) valid signature.

    @@ -282,8 +282,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    We keep the signature in the temporary location, since later we will modify the WitnessArgs object in place for message hashing.

    @@ -298,14 +298,14 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Load the current transaction hash.

    -
      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) {
    @@ -321,15 +321,15 @@ 

    secp256k1-blake160-sighash-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_state blake2b_ctx;
       blake2b_init(&blake2b_ctx, BLAKE2B_BLOCK_SIZE);
       blake2b_update(&blake2b_ctx, tx_hash, BLAKE2B_BLOCK_SIZE);
    @@ -340,8 +340,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    We’ve already saved the signature above to a different location. We can then modify the witness object in place to save both memory usage and runtime cycles. The message @@ -349,7 +349,7 @@

    secp256k1-blake160-sighash-all

    -
      memset((void *)lock_bytes_seg.ptr, 0, lock_bytes_seg.size);
    +
      memset((void *)lock_bytes_seg.ptr, 0, lock_bytes_seg.size);
  • @@ -357,15 +357,15 @@

    secp256k1-blake160-sighash-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));
  • @@ -373,8 +373,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Now let’s hash the first modified witness.

    @@ -388,15 +388,15 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Let’s loop and hash all witnesses with the same indices as the remaining input cells using current running lock script.

    -
      size_t i = 1;
    +            
      size_t i = 1;
       while (1) {
         len = MAX_WITNESS_SIZE;
    @@ -406,8 +406,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Using CKB_SOURCE_GROUP_INPUT as the source value provides us with a quick way to loop through all input cells using current running lock script. We don’t have to @@ -432,15 +432,15 @@

    secp256k1-blake160-sighash-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 *)&len, sizeof(uint64_t));
    +            
        blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t));
         blake2b_update(&blake2b_ctx, temp, len);
         i += 1;
       }
    @@ -451,8 +451,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    For safety consideration, this lock script will also hash and guard all witnesses that have index values equal to or larger than the number of input cells. It assumes all @@ -473,8 +473,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Here we are guarding input cells with any arbitrary lock script, hence we are using the plain CKB_SOURCE_INPUT source to loop all witnesses.

    @@ -498,15 +498,15 @@

    secp256k1-blake160-sighash-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 *)&len, sizeof(uint64_t));
    +            
        blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t));
         blake2b_update(&blake2b_ctx, temp, len);
         i += 1;
       }
    @@ -517,8 +517,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Now the message preparation is completed.

    @@ -532,8 +532,8 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    We are using bitcoin’s secp256k1 library for signature verification here. To the best of our knowledge, this is an unmatched @@ -544,7 +544,7 @@

    secp256k1-blake160-sighash-all

      secp256k1_context context;
    -  uint8_t secp_data[CKB_SECP256K1_DATA_SIZE];
    +  uint8_t secp_data[CKB_SECP256K1_DATA_SIZE];
       ret = ckb_secp256k1_custom_verify_only_initialize(&context, secp_data);
       if (ret != 0) {
         return ret;
    @@ -562,8 +562,8 @@ 

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    From the recoverable signature, we can derive the public key used.

    @@ -580,14 +580,14 @@

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    Let’s serialize the signature first, then generate the blake2b hash.

    -
      size_t pubkey_size = PUBKEY_SIZE;
    +            
      size_t pubkey_size = PUBKEY_SIZE;
       if (secp256k1_ec_pubkey_serialize(&context, temp, &pubkey_size, &pubkey,
                                         SECP256K1_EC_COMPRESSED) != 1) {
         return ERROR_SECP_SERIALIZE_PUBKEY;
    @@ -603,8 +603,8 @@ 

    secp256k1-blake160-sighash-all

  • -
    - +
    + §

    As mentioned above, we are only using the first 160 bits(20 bytes), if they match the value provided as the first 20 bytes of script args, the signature verification diff --git a/docs/docco.css b/docs/docco.css index b60f6fa..c3d580f 100644 --- a/docs/docco.css +++ b/docs/docco.css @@ -213,7 +213,7 @@ ul.sections > li > div { /*---------------------- Low resolutions (> 320px) ---------------------*/ @media only screen and (min-width: 320px) { - .pilwrap { display: none; } + .sswrap { display: none; } ul.sections > li > div { display: block; @@ -330,12 +330,12 @@ ul.sections > li > div { box-shadow: none; } - .pilwrap { + .sswrap { position: relative; display: inline; } - .pilcrow { + .ss { font: 12px Arial; text-decoration: none; color: #454545; @@ -345,14 +345,14 @@ ul.sections > li > div { opacity: 0; -webkit-transition: opacity 0.2s linear; } - .for-h1 .pilcrow { + .for-h1 .ss { top: 47px; } - .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { + .for-h2 .ss, .for-h3 .ss, .for-h4 .ss { top: 35px; } - ul.sections > li > div.annotation:hover .pilcrow { + ul.sections > li > div.annotation:hover .ss { opacity: 1; } } diff --git a/docs/public/fonts/roboto-black.eot b/docs/public/fonts/roboto-black.eot old mode 100755 new mode 100644 diff --git a/docs/public/fonts/roboto-black.ttf b/docs/public/fonts/roboto-black.ttf old mode 100755 new mode 100644 diff --git a/docs/public/fonts/roboto-black.woff b/docs/public/fonts/roboto-black.woff old mode 100755 new mode 100644