From 4464887e89c14b56016699ff0118e49eb911ce90 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 8 Mar 2021 15:19:16 +0100 Subject: [PATCH 001/221] fix rust-ci --- rust/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ci.yml b/rust/ci.yml index c28251e6e..5b4c95e85 100644 --- a/rust/ci.yml +++ b/rust/ci.yml @@ -134,9 +134,9 @@ deploy_rust: - find rust -name 'Cargo.toml' -exec sed -i '' -e "s/version = \"0.0.0\"/version = \""${CI_COMMIT_TAG:1}"\"/g" {} \; - cd rust/ - rm -rf in3-sys/in3-core/c/src/third-party/hidapi/ - - rm in3-sys/.gitignore + - echo "" > in3-sys/.gitignore - cd in3-sys/ && cargo publish --allow-dirty - sleep 30 - - cd ../in3-rs/ && cargo publish --allow-dirty + - cd ../in3-rs/ && cargo publish --allow-dirty || echo "Not updating in3-rs, because no new version." tags: - mac-os From 09c147223d2340d1eb362497ebbf2f174388a57e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 20 Mar 2021 23:14:45 +0100 Subject: [PATCH 002/221] bugfixes from tx_analyze --- c/src/api/eth1/abi.h | 16 ++- c/src/api/eth1/abi_decode.c | 49 +++++-- c/src/api/eth1/abi_parse.c | 9 ++ c/src/api/eth1/eth_api.c | 18 +-- c/src/api/eth1/eth_api.h | 1 + c/src/api/eth1/rpc_api.c | 68 +++++++++- c/src/cmd/in3/main.c | 54 ++++++-- c/src/core/client/execute.c | 20 +-- c/src/core/client/request.c | 7 +- c/src/core/client/request.h | 10 +- c/src/core/client/request_internal.h | 2 +- c/src/core/util/bytes.h | 6 + c/src/core/util/data.c | 35 +++-- c/src/core/util/data.h | 8 +- c/src/core/util/scache.c | 8 +- c/src/core/util/scache.h | 1 + c/src/core/util/stringbuilder.c | 28 +++- c/src/core/util/stringbuilder.h | 4 +- c/src/core/util/utils.c | 19 +++ c/src/core/util/utils.h | 5 + c/src/nodeselect/full/nodelist.c | 12 +- c/src/nodeselect/full/registry.c | 22 +-- c/src/pay/zksync/zk_deposit.c | 2 +- c/src/pay/zksync/zk_helper.c | 6 +- c/src/pay/zksync/zk_message.c | 2 +- c/src/pay/zksync/zk_musig.c | 13 +- c/src/verifier/btc/btc_target.c | 2 +- c/src/verifier/eth1/basic/eth_account.c | 2 +- c/src/verifier/eth1/basic/eth_basic.c | 19 +-- c/src/verifier/eth1/basic/eth_basic.h | 5 + c/src/verifier/eth1/basic/filter.c | 6 +- c/src/verifier/eth1/basic/sign_tx.c | 12 +- c/src/verifier/eth1/evm/accounts.c | 91 ++++++++----- c/src/verifier/eth1/evm/accounts.h | 9 +- c/src/verifier/eth1/evm/call.c | 61 +++++++-- c/src/verifier/eth1/evm/evm.c | 6 +- c/src/verifier/eth1/evm/evm.h | 54 ++++---- c/src/verifier/eth1/evm/gas.h | 127 +++++++++--------- c/src/verifier/eth1/evm/opcodes.c | 51 ++++--- c/src/verifier/eth1/full/eth_full.c | 16 ++- c/src/verifier/eth1/nano/eth_nano.c | 4 +- c/test/test_evm.c | 34 +++-- c/test/unit_tests/test_core.c | 18 +-- .../tests/integrated/negative/client_test.py | 5 - scripts/build_multi_wasm.sh | 5 +- 45 files changed, 635 insertions(+), 317 deletions(-) diff --git a/c/src/api/eth1/abi.h b/c/src/api/eth1/abi.h index 9cc7e22d6..114be8ad4 100644 --- a/c/src/api/eth1/abi.h +++ b/c/src/api/eth1/abi.h @@ -56,7 +56,8 @@ typedef enum { * Depending on the type the config is stored in the union-structs. */ typedef struct signature { - abi_coder_type_t type; /**< the type of the coder */ + abi_coder_type_t type; /**< the type of the coder */ + bool indexed; /**< marks a tuple as being indexed, which is relevant for event decoding */ union { struct { struct signature** components; /**< the pointer to an array of ponters to the types */ @@ -157,4 +158,17 @@ json_ctx_t* abi_decode( char** error /**< the a pointer to error, which will hold the error message in case of an error. This does not need to be freed, since those messages are constant strings. */ ); + +/** + * decodes bytes to a JSON-structure. + * The resulting json_ctx MUST be freed using `json_free` if not NULL. + */ +json_ctx_t* abi_decode_event( + abi_sig_t* s, /**< the signature to use */ + bytes_t topics, /**< the topics to decode */ + bytes_t data, /**< the data to decode */ + char** error /**< the a pointer to error, which will hold the error message in case of an error. This does not need to be freed, since those messages are constant strings. */ + +); + #endif // _ETH_API__ABI_H_ diff --git a/c/src/api/eth1/abi_decode.c b/c/src/api/eth1/abi_decode.c index 36d78ea17..b40edeb08 100644 --- a/c/src/api/eth1/abi_decode.c +++ b/c/src/api/eth1/abi_decode.c @@ -10,7 +10,7 @@ #include #include -static in3_ret_t decode_tuple(abi_coder_t* tuple, bytes_t data, json_ctx_t* res, int* data_read, bool as_array, char** error); +static in3_ret_t decode_tuple(abi_coder_t* tuple, bytes_t data, json_ctx_t* res, int* data_read, bool as_array, bytes_t* topics, char** error); static in3_ret_t next_word(int* offset, bytes_t* data, uint8_t** dst, char** error) { if (*offset + 32 > (int) data->len) { @@ -82,7 +82,7 @@ static in3_ret_t decode_value(abi_coder_t* c, bytes_t data, json_ctx_t* res, int break; } case ABI_TUPLE: - return decode_tuple(c, data, res, data_read, true, error); + return decode_tuple(c, data, res, data_read, true, NULL, error); case ABI_ARRAY: { int len = c->data.array.len; if (!len) { @@ -91,7 +91,8 @@ static in3_ret_t decode_value(abi_coder_t* c, bytes_t data, json_ctx_t* res, int } bool is_dynamic = abi_is_dynamic(c->data.array.component); int offset = pos; - json_create_array(res)->len |= len; + json_create_array(res); + res->result[res->len - 1].len |= len; for (int i = 0; i < len; i++) { int r = 0, start = pos; if (is_dynamic) { @@ -108,13 +109,25 @@ static in3_ret_t decode_value(abi_coder_t* c, bytes_t data, json_ctx_t* res, int return IN3_OK; } -static in3_ret_t decode_tuple(abi_coder_t* tuple, bytes_t data, json_ctx_t* res, int* data_read, bool add_array, char** error) { - if (add_array) json_create_array(res)->len |= tuple->data.tuple.len; - uint8_t* word = NULL; - int pos = 0; +static in3_ret_t decode_tuple(abi_coder_t* tuple, bytes_t data, json_ctx_t* res, int* data_read, bool add_array, bytes_t* topics, char** error) { + if (add_array) { + json_create_array(res); + res->result[res->len - 1].len |= tuple->data.tuple.len; + } + uint8_t* word = NULL; + int pos = 0; + unsigned topic_pos = 1; for (int i = 0; i < tuple->data.tuple.len; i++) { abi_coder_t* c = tuple->data.tuple.components[i]; - if (abi_is_dynamic(c)) { + if (c->indexed) { + if (!topics || topics->len < (topic_pos + 1) * 32) { + *error = "topics are too short"; + return IN3_EINVAL; + } + TRY(decode_value(c, bytes(topics->data + topic_pos * 32, 32), res, NULL, error)) + topic_pos++; + } + else if (abi_is_dynamic(c)) { TRY(next_word(&pos, &data, &word, error)) int offset = bytes_to_int(word + 28, 4); if (offset + 32 > (int) data.len) { @@ -141,7 +154,25 @@ static in3_ret_t decode_tuple(abi_coder_t* tuple, bytes_t data, json_ctx_t* res, json_ctx_t* abi_decode(abi_sig_t* s, bytes_t data, char** error) { json_ctx_t* res = json_create(); abi_coder_t* c = s->output ? s->output : s->input; - in3_ret_t failed = decode_tuple(c, data, res, NULL, s->return_tuple || c->data.tuple.len != 1, error); + in3_ret_t failed = decode_tuple(c, data, res, NULL, s->return_tuple || c->data.tuple.len != 1, NULL, error); if (failed && res) json_free(res); return *error ? NULL : res; } + +json_ctx_t* abi_decode_event( + abi_sig_t* s, /**< the signature to use */ + bytes_t topics, /**< the topics to decode */ + bytes_t data, /**< the data to decode */ + char** error /**< the a pointer to error, which will hold the error message in case of an error. This does not need to be freed, since those messages are constant strings. */ + +) { + if (topics.len < 32 || memcmp(topics.data, s->fn_hash, 4)) { + *error = "The Topic does not match the event signature"; + return NULL; + } + json_ctx_t* res = json_create(); + abi_coder_t* c = s->output ? s->output : s->input; + in3_ret_t failed = decode_tuple(c, data, res, NULL, s->return_tuple || c->data.tuple.len != 1, &topics, error); + if (failed && res) json_free(res); + return *error ? NULL : res; +} \ No newline at end of file diff --git a/c/src/api/eth1/abi_parse.c b/c/src/api/eth1/abi_parse.c index 5f1dbd0c3..d2822f683 100644 --- a/c/src/api/eth1/abi_parse.c +++ b/c/src/api/eth1/abi_parse.c @@ -126,13 +126,20 @@ static abi_coder_t* create_tuple(char* val, char** error, char** next) { int tl = 0; abi_coder_t* tuple = _calloc(1, sizeof(abi_coder_t)); tuple->type = ABI_TUPLE; + bool indexed = false; for (char c = *val; !*error; c = *(++val)) { if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { + if (tl == 40) return abi_error(error, "toke too long", tuple); token[tl++] = c; continue; } if (c == ' ' && !tl) continue; + if (c == ' ' && tl == 7 && strncmp(token, "indexed", 7) == 0) { + tl = 0; + indexed = true; + continue; + } abi_coder_t* coder = NULL; if (tl) { @@ -162,6 +169,8 @@ static abi_coder_t* create_tuple(char* val, char** error, char** next) { } if (coder) { + coder->indexed = indexed; + indexed = false; tuple->data.tuple.components = tuple->data.tuple.len ? _realloc(tuple->data.tuple.components, (tuple->data.tuple.len + 1) * sizeof(abi_coder_t*), tuple->data.tuple.len * sizeof(abi_coder_t*)) : _malloc(sizeof(abi_coder_t*)); diff --git a/c/src/api/eth1/eth_api.c b/c/src/api/eth1/eth_api.c index fd308d67f..5871af769 100644 --- a/c/src/api/eth1/eth_api.c +++ b/c/src/api/eth1/eth_api.c @@ -336,29 +336,29 @@ static void* eth_call_fn_intern(in3_t* in3, address_t contract, eth_blknum_t blo bytes_t data = {0}; if (!error) { json_ctx_t* in_data = json_create(); - d_token_t* args = json_create_array(in_data); + int args = json_create_array(in_data); for (int i = 0; i < req->input->data.tuple.len && !error; i++) { abi_coder_t* p = req->input->data.tuple.components[i]; switch (p->type) { case ABI_BOOL: - json_array_add_value(args, json_create_bool(in_data, va_arg(ap, int))); + json_array_add_value(in_data, args, json_create_bool(in_data, va_arg(ap, int))); break; case ABI_ADDRESS: - json_array_add_value(args, json_create_bytes(in_data, bytes(va_arg(ap, uint8_t*), 20))); + json_array_add_value(in_data, args, json_create_bytes(in_data, bytes(va_arg(ap, uint8_t*), 20))); break; case ABI_BYTES: - json_array_add_value(args, json_create_bytes(in_data, va_arg(ap, bytes_t))); + json_array_add_value(in_data, args, json_create_bytes(in_data, va_arg(ap, bytes_t))); break; case ABI_STRING: - json_array_add_value(args, json_create_string(in_data, va_arg(ap, char*), -1)); + json_array_add_value(in_data, args, json_create_string(in_data, va_arg(ap, char*), -1)); break; case ABI_NUMBER: { if (p->data.number.size <= 32) - json_array_add_value(args, json_create_int(in_data, va_arg(ap, uint32_t))); + json_array_add_value(in_data, args, json_create_int(in_data, va_arg(ap, uint32_t))); else if (p->data.number.size <= 64) - json_array_add_value(args, json_create_int(in_data, va_arg(ap, uint64_t))); + json_array_add_value(in_data, args, json_create_int(in_data, va_arg(ap, uint64_t))); else - json_array_add_value(args, json_create_bytes(in_data, bytes(va_arg(ap, uint256_t).data, 32))); + json_array_add_value(in_data, args, json_create_bytes(in_data, bytes(va_arg(ap, uint256_t).data, 32))); break; } default: @@ -366,7 +366,7 @@ static void* eth_call_fn_intern(in3_t* in3, address_t contract, eth_blknum_t blo } } - if (!error) data = abi_encode(req, args, &error); + if (!error) data = abi_encode(req, in_data->result + args, &error); json_free(in_data); } diff --git a/c/src/api/eth1/eth_api.h b/c/src/api/eth1/eth_api.h index f5e03e51d..56855fbea 100644 --- a/c/src/api/eth1/eth_api.h +++ b/c/src/api/eth1/eth_api.h @@ -183,6 +183,7 @@ char* eth_wait_for_receipt(in3_t* in3, bytes32_t tx_hash); void eth_log_free(eth_log_t* log); /**< Frees a eth_log_t object */ void eth_tx_receipt_free(eth_tx_receipt_t* txr); /**< Frees a eth_tx_receipt_t object */ int string_val_to_bytes(char* val, char* unit, bytes32_t target); /**< reades the string as hex or decimal and converts it into bytes. the value may also contains a suffix as unit like '1.5eth` which will convert it into wei. the target-pointer must be at least as big as the strlen. The length of the bytes will be returned or a negative value in case of an error.*/ +char* bytes_to_string_val(bytes_t wei, int exp, int digits); /**< converts the bytes value to a decimal string */ in3_ret_t in3_register_eth_api(in3_t* c); /**< this function should only be called once and will register the eth-API verifier.*/ #ifdef __cplusplus } diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index bd0d1a162..24dacbc80 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -38,6 +38,7 @@ #include "../../core/util/debug.h" #include "../../core/util/log.h" #include "../../core/util/mem.h" +#include "../../third-party/crypto/bignum.h" #include "../../third-party/crypto/ecdsa.h" #include "../../third-party/crypto/rand.h" #include "../../third-party/crypto/secp256k1.h" @@ -219,7 +220,7 @@ int string_val_to_bytes(char* val, char* unit, bytes32_t target) { char* dst = alloca(l + exp + 10); char* dot = strchr(val, '.'); if (!dot) - memcpy(dst, val, (p = l) + 1); + memcpy(dst, val, (p = nl) + 1); else if (dot - val != 1 || *val != '0') memcpy(dst, val, (p = dot - val) + 1); dst[p + exp] = 0; @@ -275,6 +276,70 @@ static in3_ret_t in3_toWei(in3_rpc_handle_ctx_t* ctx) { : in3_rpc_handle_with_bytes(ctx, bytes(tmp, (uint32_t) s)); } +char* bytes_to_string_val(bytes_t wei, int exp, int digits) { + char tmp[300]; + bytes32_t val = {0}; + memcpy(val + 32 - wei.len, wei.data, wei.len); + bignum256 bn; + bn_read_be(val, &bn); + size_t l = bn_format(&bn, "", "", 0, 0, false, tmp, 300); + if (exp) { + if (l <= (size_t) exp) { + memmove(tmp + exp - l + 1, tmp, l + 1); + memset(tmp, '0', exp - l + 1); + l += exp - l + 1; + } + memmove(tmp + l - exp + 1, tmp + l - exp, exp + 1); + tmp[l - exp] = '.'; + l++; + } + if (digits == -1 && exp) + for (int i = l - 1;; i--) { + if (tmp[i] == '0') + tmp[i] = 0; + else if (tmp[i] == '.') { + tmp[i] = 0; + break; + } + else + break; + } + else if (digits == 0) + tmp[l - exp + digits - 1] = 0; + else if (digits < exp) + tmp[l - exp + digits] = 0; + + return _strdupn(tmp, -1); +} + +static in3_ret_t in3_fromWei(in3_rpc_handle_ctx_t* ctx) { + if (!ctx->params || d_len(ctx->params) < 1) return req_set_error(ctx->req, "must have 1 params as number or bytes", IN3_EINVAL); + bytes_t val = d_to_bytes(ctx->params + 1); + d_token_t* unit = d_get_at(ctx->params, 1); + int exp = 0; + if (d_type(unit) == T_STRING) { + char* u = d_string(unit); + for (int i = 0; UNITS[i]; i += 2) { + if (strcmp(UNITS[i], u) == 0) { + exp = *UNITS[i + 1]; + break; + } + else if (!UNITS[i + 2]) + return req_set_error(ctx->req, "the unit can not be found", IN3_EINVAL); + } + } + else if (d_type(unit) == T_INTEGER) + exp = d_int(unit); + else + return req_set_error(ctx->req, "the unit must be eth-unit or a exponent", IN3_EINVAL); + + int digits = (unit = d_get_at(ctx->params, 2)) ? d_int(unit) : -1; + char* s = bytes_to_string_val(val, exp, digits); + in3_ret_t r = in3_rpc_handle_with_string(ctx, s); + _free(s); + return r; +} + static in3_ret_t in3_config(in3_rpc_handle_ctx_t* ctx) { if (!ctx->params || d_len(ctx->params) != 1 || d_type(ctx->params + 1) != T_OBJECT) return req_set_error(ctx->req, "no valid config-object as argument", IN3_EINVAL); @@ -494,6 +559,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("keccak", in3_sha3(ctx)) TRY_RPC("sha256", in3_sha256(ctx)) TRY_RPC("in3_toWei", in3_toWei(ctx)) + TRY_RPC("in3_fromWei", in3_fromWei(ctx)) TRY_RPC("in3_config", in3_config(ctx)) TRY_RPC("in3_getConfig", in3_getConfig(ctx)) TRY_RPC("in3_pk2address", in3_pk2address(ctx)) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index ea0784ce8..7d63e3153 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -106,6 +106,7 @@ void show_help(char* name) { -am only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed. All other will be rejected.\n\ -b, -block the blocknumber to use when making calls. could be either latest (default),earliest or a hexnumbner\n\ -to the target address of the call\n\ +-from the sender of a call or tx (only needed if no signer is registered)\n\ -d, -data the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin.\n\ -gp,-gas_price the gas price to use when sending transactions. (default: use eth_gasPrice) \n\ -gas the gas limit to use when sending transactions. (default: 100000) \n\ @@ -122,6 +123,7 @@ void show_help(char* name) { -debug if given incubed will output debug information when executing. \n\ -k 32bytes raw private key to sign requests.\n\ -q quit. no additional output. \n\ +-h human readable, which removes the json -structure and oly displays the values.\n\ -tr runs test request when showing in3_weights \n\ -thr runs test request including health-check when showing in3_weights \n\ -ms adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) \n\ @@ -429,7 +431,7 @@ void set_chain_id(in3_t* c, char* id) { } // prepare a eth_call or eth_sendTransaction -abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data) { +abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data, char* from) { char* error = NULL; bytes_t rdata = {0}; abi_sig_t* req = fn_sig ? abi_sig_create(fn_sig, &error) : NULL; // only if we have a function signature, we will parse it and create a call_request. @@ -477,6 +479,12 @@ abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, ui sb_add_chars(params, value); sb_add_chars(params, "\""); } + if (from) { + sb_add_chars(params, ", \"from\":\""); + sb_add_chars(params, from); + sb_add_chars(params, "\""); + } + if (gas_price) { long_to_bytes(gas_price, gasdata); b_optimize_len(&g_bytes); @@ -497,10 +505,20 @@ abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, ui void print_val(d_token_t* t) { switch (d_type(t)) { case T_ARRAY: - case T_OBJECT: - for (d_iterator_t it = d_iter(t); it.left; d_iter_next(&it)) - print_val(it.token); - break; + case T_OBJECT: { + char* level = d_get_string(t, key("level")); + if (level) { + char* msg = d_get_string(t, key("msg")); + if (strcmp(level, "main") == 0) recorder_print(0, COLOR_GREEN_STR "\n", msg); + if (strcmp(level, "info") == 0) recorder_print(0, "%s\n", msg); + if (strcmp(level, "warning") == 0) recorder_print(0, COLOR_YELLOW_STR "\n", msg); + if (strcmp(level, "error") == 0) recorder_print(0, COLOR_RED_STR "\n", msg); + } + else { + for (d_iterator_t it = d_iter(t); it.left; d_iter_next(&it)) + print_val(it.token); + } + } break; case T_BOOLEAN: recorder_print(0, "%s\n", d_int(t) ? "true" : "false"); break; @@ -734,6 +752,8 @@ int main(int argc, char* argv[]) { char* sig_type = "raw"; bool to_eth = false; char* rc = "2"; + bool human_readable = false; + char* from = NULL; in3_plugin_register(c, PLGN_ACT_TRANSPORT, debug_transport, NULL, true); @@ -859,6 +879,8 @@ int main(int argc, char* argv[]) { recorder_write_start(c, argv[++i], argc, argv); else if (strcmp(argv[i], "-fi") == 0) recorder_read_start(c, argv[++i]); + else if (strcmp(argv[i], "-h") == 0) + human_readable = true; #ifdef NODESELECT_DEF else if (strcmp(argv[i], "-nl") == 0) set_nodelist(c, argv[++i], false); @@ -902,6 +924,8 @@ int main(int argc, char* argv[]) { value = get_wei(argv[++i]); else if (strcmp(argv[i], "-port") == 0) port = argv[++i]; + else if (strcmp(argv[i], "-from") == 0) + from = argv[++i]; else if (strcmp(argv[i], "-am") == 0) allowed_methods = argv[++i]; else if (strcmp(argv[i], "-os") == 0) @@ -1018,7 +1042,7 @@ int main(int argc, char* argv[]) { // call -> eth_call if (strcmp(method, "call") == 0) { - req = prepare_tx(sig, resolve(c, to), args, block_number, 0, 0, NULL, data); + req = prepare_tx(sig, resolve(c, to), args, block_number, 0, 0, NULL, data, from); method = "eth_call"; } else if (strcmp(method, "abi_encode") == 0) { @@ -1206,8 +1230,11 @@ int main(int argc, char* argv[]) { } #endif else if (strcmp(method, "send") == 0) { - prepare_tx(sig, resolve(c, to), args, NULL, gas_limit, gas_price, value, data); - method = wait ? "eth_sendTransactionAndWait" : "eth_sendTransaction"; + prepare_tx(sig, resolve(c, to), args, NULL, gas_limit, gas_price, value, data, from); + if (only_show_raw_tx && (c->plugin_acts & (PLGN_ACT_SIGN | PLGN_ACT_SIGN_ACCOUNT)) == 0) + method = "in3_prepareTx"; + else + method = wait ? "eth_sendTransactionAndWait" : "eth_sendTransaction"; } else if (strcmp(method, "sign") == 0) { if (!data) die("no data given"); @@ -1409,7 +1436,7 @@ int main(int argc, char* argv[]) { } // if the result is a string, we remove the quotes - if (result[0] == '"' && result[strlen(result) - 1] == '"') { + if (!human_readable && result[0] == '"' && result[strlen(result) - 1] == '"') { memmove(result, result + 1, strlen(result)); result[strlen(result) - 1] = 0; } @@ -1429,6 +1456,15 @@ int main(int argc, char* argv[]) { } // if not we simply print the result } + else if (human_readable) { + json_ctx_t* jctx = parse_json(result); + if (jctx) + print_val(jctx->result); + else + recorder_print(0, "%s\n", result); + } + else if (only_show_raw_tx && strcmp(method, "in3_prepareTx") == 0 && from) + recorder_print(0, "%s %s\n", result, from); else { if (to_eth && result[0] == '0' && result[1] == 'x' && strlen(result) <= 18) { double val = char_to_long(result, strlen(result)); diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c index 3b50eddde..050afaf08 100644 --- a/c/src/core/client/execute.c +++ b/c/src/core/client/execute.c @@ -822,12 +822,14 @@ void in3_sign_ctx_set_signature( _free(sign_ctx->signature.data); } -in3_req_t* req_find_required(const in3_req_t* parent, const char* search_method) { - in3_req_t* sub_ctx = parent->required; - while (sub_ctx) { - if (!sub_ctx->requests) continue; - if (req_is_method(sub_ctx, search_method)) return sub_ctx; - sub_ctx = sub_ctx->required; +in3_req_t* req_find_required(const in3_req_t* parent, const char* search_method, const char* param_query) { + for (in3_req_t* r = parent->required; r; r = r->required) { + if (!r->requests) continue; + if (req_is_method(r, search_method)) { + d_token_t* params = d_get(r->requests[0], K_PARAMS); + if (param_query && (!params || !params->data || !str_find((void*) params->data, param_query))) continue; + return r; + } } return NULL; } @@ -927,9 +929,6 @@ in3_ret_t in3_req_execute(in3_req_t* req) { // is it a valid request? if (!req->request_context || d_type(d_get(req->requests[0], K_METHOD)) != T_STRING) return req_set_error(req, "No Method defined", IN3_ECONFIG); - // if there is response we are done. - if (req->response_context && req->verification_state == IN3_OK) return IN3_OK; - // if we have required-contextes, we need to check them first if (req->required && (ret = in3_req_execute(req->required))) { if (ret == IN3_EIGNORE) @@ -938,6 +937,9 @@ in3_ret_t in3_req_execute(in3_req_t* req) { return req_set_error(req, get_error_message(req->required, ret), ret); } + // if there is response we are done. + if (req->response_context && req->verification_state == IN3_OK) return IN3_OK; + in3_log_debug("ctx_execute %s ... attempt %i\n", d_get_string(req->requests[0], K_METHOD), req->attempt + 1); switch (req->type) { diff --git a/c/src/core/client/request.c b/c/src/core/client/request.c index c06ab8014..74f063c77 100644 --- a/c/src/core/client/request.c +++ b/c/src/core/client/request.c @@ -312,7 +312,7 @@ in3_ret_t in3_rpc_handle_with_int(in3_rpc_handle_ctx_t* hctx, uint64_t value) { return in3_rpc_handle_with_string(hctx, s); } -in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, char* in3, d_token_t** result) { +in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, char* in3, d_token_t** result, in3_req_t** child) { bool use_cache = strcmp(method, "eth_sendTransaction") == 0; if (params == NULL) params = ""; char* req = NULL; @@ -343,6 +343,8 @@ in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, ch if (strncmp(params, p.data + 1, p.len - 2) == 0) break; } + if (ctx && child) *child = ctx; + if (ctx) switch (in3_req_state(ctx)) { case REQ_ERROR: @@ -369,6 +371,7 @@ in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, ch } ctx = req_new(parent->client, req); if (!ctx) return req_set_error(parent, "Invalid request!", IN3_ERPC); + if (child) *child = ctx; if (use_cache) in3_cache_add_ptr(&ctx->cache, req)->props = CACHE_PROP_SRC_REQ; in3_ret_t ret = req_add_required(parent, ctx); @@ -407,7 +410,7 @@ in3_ret_t req_require_signature(in3_req_t* ctx, d_signature_type_t type, bytes_t // get the signature from required const char* method = type == SIGN_EC_HASH ? "sign_ec_hash" : "sign_ec_raw"; - in3_req_t* c = req_find_required(ctx, method); + in3_req_t* c = req_find_required(ctx, method, NULL); if (c) switch (in3_req_state(c)) { case REQ_ERROR: diff --git a/c/src/core/client/request.h b/c/src/core/client/request.h index 5250efaae..90f23adb0 100644 --- a/c/src/core/client/request.h +++ b/c/src/core/client/request.h @@ -339,7 +339,7 @@ NONULL void req_free( * ```c in3_ret_t get_from_nodes(in3_req_t* parent, char* method, char* params, bytes_t* dst) { // check if the method is already existing - in3_req_t* req = req_find_required(parent, method); + in3_req_t* req = req_find_required(parent, method, NULL); if (ctx) { // found one - so we check if it is useable. switch (in3_req_state(ctx)) { @@ -386,9 +386,11 @@ NONULL in3_ret_t req_add_required( * * This method is used internaly to find a previously added context. */ -NONULL in3_req_t* req_find_required( - const in3_req_t* parent, /**< [in] the current request context. */ - const char* method /**< [in] the method of the rpc-request. */ +NONULL_FOR((1, 2)) +in3_req_t* req_find_required( + const in3_req_t* parent, /**< [in] the current request context. */ + const char* method, /**< [in] the method of the rpc-request. */ + const char* param_query /**< [in] a optional string within thew params. */ ); /** * removes a required context after usage. diff --git a/c/src/core/client/request_internal.h b/c/src/core/client/request_internal.h index 64e80f383..80d0f552f 100644 --- a/c/src/core/client/request_internal.h +++ b/c/src/core/client/request_internal.h @@ -93,7 +93,7 @@ in3_ret_t req_handle_failable( ); NONULL_FOR((1, 2, 3, 5)) -in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, char* in3, d_token_t** result); +in3_ret_t req_send_sub_request(in3_req_t* parent, char* method, char* params, char* in3, d_token_t** result, in3_req_t** child); NONULL in3_ret_t req_require_signature(in3_req_t* req, d_signature_type_t type, bytes_t* sig, bytes_t raw_data, bytes_t from); NONULL in3_ret_t in3_retry_same_node(in3_req_t* req); diff --git a/c/src/core/util/bytes.h b/c/src/core/util/bytes.h index de07d151f..0aa9fe3a1 100644 --- a/c/src/core/util/bytes.h +++ b/c/src/core/util/bytes.h @@ -123,6 +123,12 @@ NONULL static inline void b_optimize_len(bytes_t* b) { } } +static inline int b_compare(bytes_t a, bytes_t b) { + return (a.len == b.len) + ? memcmp(a.data, b.data, a.len) + : ((int) a.len) - ((int) b.len); +} + #define b_to_stack(d) \ { \ bytes_t o = d; \ diff --git a/c/src/core/util/data.c b/c/src/core/util/data.c index f062a4716..7ad8bfc56 100644 --- a/c/src/core/util/data.c +++ b/c/src/core/util/data.c @@ -418,6 +418,7 @@ NONULL int parse_string(json_ctx_t* jp, d_token_t* item) { char* start = jp->c; size_t l, i; int n; + bool ishex = false; while (true) { switch (*(jp->c++)) { @@ -426,8 +427,17 @@ NONULL int parse_string(json_ctx_t* jp, d_token_t* item) { case '\'': case '"': if (start[-1] != jp->c[-1]) continue; - l = jp->c - start - 1; - if (l > 1 && *start == '0' && start[1] == 'x' && *(start - 1) != '\'') { + l = jp->c - start - 1; + ishex = l > 1 && *start == '0' && start[1] == 'x' && *(start - 1) != '\''; + if (ishex) + for (size_t n = 2; n < l; n++) { + char cc = start[n]; + if (!((cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f') || (cc >= 'A' && cc <= 'F'))) { + ishex = false; + break; + } + } + if (ishex) { // this is a hex-value if (l == 2) { // empty byte array @@ -880,24 +890,25 @@ d_token_t* json_create_bytes(json_ctx_t* jp, bytes_t value) { return r; } -d_token_t* json_create_object(json_ctx_t* jp) { - return next_item(jp, T_OBJECT, 0); +int json_create_object(json_ctx_t* jp) { + next_item(jp, T_OBJECT, 0); + return jp->len - 1; } -d_token_t* json_create_array(json_ctx_t* jp) { - return next_item(jp, T_ARRAY, 0); +int json_create_array(json_ctx_t* jp) { + next_item(jp, T_ARRAY, 0); + return jp->len - 1; } -d_token_t* json_object_add_prop(d_token_t* object, d_key_t key, d_token_t* value) { - object->len++; +void json_object_add_prop(json_ctx_t* jp, int ob_index, d_key_t key, d_token_t* value) { + jp->result[ob_index].len++; value->key = key; - return object; } -d_token_t* json_array_add_value(d_token_t* object, d_token_t* value) { - value->key = object->len; +void json_array_add_value(json_ctx_t* jp, int ob_index, d_token_t* value) { + d_token_t* object = jp->result + ob_index; + value->key = object->len; object->len++; - return object; } static void write_token_count(bytes_builder_t* bb, int len) { diff --git a/c/src/core/util/data.h b/c/src/core/util/data.h index 016a41daa..1f9126a4e 100644 --- a/c/src/core/util/data.h +++ b/c/src/core/util/data.h @@ -151,10 +151,10 @@ NONULL d_token_t* json_create_bool(json_ctx_t* jp, bool value); NONULL d_token_t* json_create_int(json_ctx_t* jp, uint64_t value); NONULL d_token_t* json_create_string(json_ctx_t* jp, char* value, int len); NONULL d_token_t* json_create_bytes(json_ctx_t* jp, bytes_t value); -NONULL d_token_t* json_create_object(json_ctx_t* jp); -NONULL d_token_t* json_create_array(json_ctx_t* jp); -NONULL d_token_t* json_object_add_prop(d_token_t* object, d_key_t key, d_token_t* value); -NONULL d_token_t* json_array_add_value(d_token_t* object, d_token_t* value); +NONULL int json_create_object(json_ctx_t* jp); +NONULL int json_create_array(json_ctx_t* jp); +NONULL void json_object_add_prop(json_ctx_t* jp, int ob_index, d_key_t key, d_token_t* value); +NONULL void json_array_add_value(json_ctx_t* jp, int parent_index, d_token_t* value); // Helper function to map string to 2byte keys (only for tests or debugging) char* d_get_keystr(json_ctx_t* json, d_key_t k); /**< returns the string for a key. This only works for index keys or known keys! */ diff --git a/c/src/core/util/scache.c b/c/src/core/util/scache.c index 63795794e..54bbed85c 100644 --- a/c/src/core/util/scache.c +++ b/c/src/core/util/scache.c @@ -33,6 +33,7 @@ *******************************************************************************/ #include "scache.h" +#include "data.h" #include "mem.h" bytes_t* in3_cache_get_entry(cache_entry_t* cache, bytes_t* key) { @@ -44,7 +45,12 @@ bytes_t* in3_cache_get_entry(cache_entry_t* cache, bytes_t* key) { void in3_cache_free(cache_entry_t* cache, bool is_external) { cache_entry_t* p = NULL; while (cache) { - if (cache->key.data) _free(cache->key.data); + if (cache->key.data) { + if (cache->props & CACHE_PROP_JSON) + json_free((void*) cache->value.data); + else + _free(cache->key.data); + } if (cache->props & CACHE_PROP_MUST_FREE && ((cache->props & CACHE_PROP_ONLY_EXTERNAL) == 0 || is_external)) _free(cache->value.data); p = cache; diff --git a/c/src/core/util/scache.h b/c/src/core/util/scache.h index 4f3970b64..6df98fa4b 100644 --- a/c/src/core/util/scache.h +++ b/c/src/core/util/scache.h @@ -53,6 +53,7 @@ typedef enum cache_props { CACHE_PROP_MUST_FREE = 0x1, /**< indicates the content must be freed*/ CACHE_PROP_SRC_REQ = 0x2, /**< the value holds the src-request */ CACHE_PROP_ONLY_EXTERNAL = 0x4, /**< should only be freed if the context is external */ + CACHE_PROP_JSON = 0x8, /**< indicates the content is a json_ctxt and must be freed as such*/ CACHE_PROP_PAYMENT = 0x80 /**< This cache-entry is a payment.data */ } cache_props_t; /** diff --git a/c/src/core/util/stringbuilder.c b/c/src/core/util/stringbuilder.c index d0da8876a..62c0be58d 100644 --- a/c/src/core/util/stringbuilder.c +++ b/c/src/core/util/stringbuilder.c @@ -183,9 +183,9 @@ sb_t* sb_add_hexuint_l(sb_t* sb, uintmax_t uint, size_t l) { return sb; } -sb_t* sb_add_int(sb_t* sb, uint64_t val) { - char tmp[19]; // UINT64_MAX => 18446744073709551615 => 0xFFFFFFFFFFFFFFFF - int l = sprintf(tmp, "%" PRId64, val); +sb_t* sb_add_int(sb_t* sb, int64_t val) { + char tmp[30]; // UINT64_MAX => 18446744073709551615 => 0xFFFFFFFFFFFFFFFF + int l = sprintf(tmp, "%" PRIi64, val); check_size(sb, l); memcpy(sb->data + sb->len, tmp, l); sb->len += l; @@ -227,10 +227,17 @@ char* format_json(const char* json) { return _sb.data; } -sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, unsigned int fix_size) { +static const uint8_t zero = 0; + +sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, int fix_size) { + if (fix_size == -1) { + if (b.len == 0) b = bytes((uint8_t*) &zero, 1); + b_optimize_len(&b); + } int l = prefix ? strlen(prefix) : 0; int bl = b.len * 2; - if (fix_size > b.len) bl = fix_size * 2; + if (fix_size > (int) b.len) bl = fix_size * 2; + if (fix_size == -1 && b.len && *b.data < 16) bl--; l += bl; if (l == 0) return sb; check_size(sb, l); @@ -238,9 +245,16 @@ sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, unsigned int fix_size) sb->len += l; sb->data[sb->len] = 0; int p = sb->len - bl; - for (unsigned int i = b.len; i < fix_size; i++, p += 2) + for (int i = (int) b.len; i < fix_size; i++, p += 2) sb->data[p] = sb->data[p + 1] = '0'; - bytes_to_hex(b.data, b.len, sb->data + p); + if (fix_size == -1 && b.len && *b.data < 16) { + char tmp[3]; + bytes_to_hex(b.data, 1, tmp); + sb->data[p] = tmp[1]; + bytes_to_hex(b.data + 1, b.len - 1, sb->data + p + 1); + } + else + bytes_to_hex(b.data, b.len, sb->data + p); return sb; } diff --git a/c/src/core/util/stringbuilder.h b/c/src/core/util/stringbuilder.h index 8a652de4e..ad75dd236 100644 --- a/c/src/core/util/stringbuilder.h +++ b/c/src/core/util/stringbuilder.h @@ -82,10 +82,10 @@ NONULL_FOR((1, 3)) sb_t* sb_add_bytes(sb_t* sb, const char* prefix, const bytes_t* bytes, int len, bool as_array); /**< add bytes as 0x-prefixed hexcoded string (including an optional prefix), if len>1 is passed bytes maybe an array ( if as_array==true) */ NONULL sb_t* sb_add_hexuint_l(sb_t* sb, uintmax_t uint, size_t l); /**< add a integer value as hexcoded, 0x-prefixed string*/ NONULL sb_t* sb_add_escaped_chars(sb_t* sb, const char* chars); /**< add chars but escapes all quotes */ -NONULL sb_t* sb_add_int(sb_t* sb, uint64_t val); /**< adds a numeric value to the stringbuilder */ +NONULL sb_t* sb_add_int(sb_t* sb, int64_t val); /**< adds a numeric value to the stringbuilder */ NONULL char* format_json(const char* json); /**< format a json string and returns a new string, which needs to be freed */ NONULL_FOR((1)) -sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, unsigned int fix_size); +sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, int fix_size); sb_t* sb_print(sb_t* sb, const char* fmt, ...); sb_t* sb_vprint(sb_t* sb, const char* fmt, va_list args); diff --git a/c/src/core/util/utils.c b/c/src/core/util/utils.c index 09a4f2409..54d4ee67b 100644 --- a/c/src/core/util/utils.c +++ b/c/src/core/util/utils.c @@ -398,3 +398,22 @@ int64_t parse_float_val(const char* data, int32_t expo) { for (; expo > 0; expo--) val *= 10; return val; } + +void b256_add(bytes32_t a, uint8_t* b, wlen_t len_b) { + optimize_len(b, len_b); + uint8_t * pa = a + 31, *pb = b + len_b - 1; + uint_fast16_t carry = 0; + do { + carry += *pa + *pb; + *pa = carry & 0xFF; + carry >>= 8; + pb--, pa--; + } while (b == pb); + + while (carry && pa >= a) { + carry += *pa; + *pa = carry & 0xFF; + carry >>= 8; + pa--; + } +} diff --git a/c/src/core/util/utils.h b/c/src/core/util/utils.h index 64acd9d1c..9f6a71cf8 100644 --- a/c/src/core/util/utils.h +++ b/c/src/core/util/utils.h @@ -319,6 +319,11 @@ int64_t parse_float_val(const char* data, /**< the data string*/ int32_t expo /**< the exponent */ ); +/** + * simple add function, which adds the bytes (b) to a + */ +void b256_add(bytes32_t a, uint8_t* b, wlen_t len_b); + #ifdef THREADSAFE #define _NAME(x, y) x##y #if defined(_MSC_VER) || defined(__MINGW32__) diff --git a/c/src/nodeselect/full/nodelist.c b/c/src/nodeselect/full/nodelist.c index 8147f1187..a7bcec6cd 100644 --- a/c/src/nodeselect/full/nodelist.c +++ b/c/src/nodeselect/full/nodelist.c @@ -214,7 +214,7 @@ NONULL static in3_ret_t in3_client_fill_chain_whitelist(in3_nodeselect_def_t* da NONULL static in3_ret_t update_nodelist(in3_t* c, in3_nodeselect_def_t* data, in3_req_t* parent_ctx) { // is there a useable required ctx? - in3_req_t* ctx = req_find_required(parent_ctx, "in3_nodeList"); + in3_req_t* ctx = req_find_required(parent_ctx, "in3_nodeList", NULL); if (ctx) { if (in3_req_state(ctx) == REQ_ERROR || (in3_req_state(ctx) == REQ_SUCCESS && !d_get(ctx->responses[0], K_RESULT))) { @@ -289,7 +289,7 @@ NONULL static in3_ret_t update_nodelist(in3_t* c, in3_nodeselect_def_t* data, in #ifdef NODESELECT_DEF_WL NONULL static in3_ret_t update_whitelist(in3_t* c, in3_nodeselect_def_t* data, in3_req_t* parent_ctx) { // is there a useable required ctx? - in3_req_t* ctx = req_find_required(parent_ctx, "in3_whiteList"); + in3_req_t* ctx = req_find_required(parent_ctx, "in3_whiteList", NULL); if (ctx) switch (in3_req_state(ctx)) { @@ -473,7 +473,7 @@ in3_ret_t in3_node_list_get(in3_req_t* ctx, in3_nodeselect_def_t* data, bool upd in3_ret_t res; // do we need to update the nodelist? - if (data->nodelist_upd8_params || update || req_find_required(ctx, "in3_nodeList")) { + if (data->nodelist_upd8_params || update || req_find_required(ctx, "in3_nodeList", NULL)) { // skip update if update has been postponed or there's already one in progress if (postpone_update(data) || update_in_progress(ctx)) goto SKIP_UPDATE; @@ -487,9 +487,9 @@ in3_ret_t in3_node_list_get(in3_req_t* ctx, in3_nodeselect_def_t* data, bool upd #ifdef NODESELECT_DEF_WL // do we need to update the whitelist? - if (data->whitelist // only if we have a whitelist - && (data->whitelist->needs_update || update || req_find_required(ctx, "in3_whiteList")) // which has the needs_update-flag (or forced) or we have already sent the request and are now picking up the result - && !memiszero(data->whitelist->contract, 20)) { // and we need to have a contract set, zero-contract = manual whitelist, which will not be updated. + if (data->whitelist // only if we have a whitelist + && (data->whitelist->needs_update || update || req_find_required(ctx, "in3_whiteList", NULL)) // which has the needs_update-flag (or forced) or we have already sent the request and are now picking up the result + && !memiszero(data->whitelist->contract, 20)) { // and we need to have a contract set, zero-contract = manual whitelist, which will not be updated. data->whitelist->needs_update = false; // now update the whiteList res = update_whitelist(ctx->client, data, ctx); diff --git a/c/src/nodeselect/full/registry.c b/c/src/nodeselect/full/registry.c index 57abd6ab8..b869aa81b 100644 --- a/c/src/nodeselect/full/registry.c +++ b/c/src/nodeselect/full/registry.c @@ -36,6 +36,7 @@ #include "../../core/client/keys.h" #include "../../core/client/request.h" #include "../../core/util/mem.h" +#include "../../core/util/utils.h" #include "../../verifier/eth1/nano/eth_nano.h" #include "../../verifier/eth1/nano/merkle.h" #include "../../verifier/eth1/nano/rlp.h" @@ -44,25 +45,6 @@ #define SERVER_STRUCT_SIZE 6 -static void big_add(bytes32_t a, uint8_t* b, wlen_t len_b) { - optimize_len(b, len_b); - uint8_t * pa = a + 31, *pb = b + len_b - 1; - uint_fast16_t carry = 0; - do { - carry += *pa + *pb; - *pa = carry & 0xFF; - carry >>= 8; - pb--, pa--; - } while (b == pb); - - while (carry && pa >= a) { - carry += *pa; - *pa = carry & 0xFF; - carry >>= 8; - pa--; - } -} - static in3_ret_t get_storage_value(d_token_t* storage_proofs, uint8_t* skey, bytes32_t value) { uint_fast16_t key_len = 32; optimize_len(skey, key_len); @@ -137,7 +119,7 @@ static uint8_t* get_storage_array_key(uint32_t pos, uint32_t array_index, uint32 uint8_t tmp[4]; int_to_bytes(array_index * struct_size + struct_pos, tmp); - big_add(dst, tmp, 4); + b256_add(dst, tmp, 4); return dst; } diff --git a/c/src/pay/zksync/zk_deposit.c b/c/src/pay/zksync/zk_deposit.c index a8f5d7931..5c2c92894 100644 --- a/c/src/pay/zksync/zk_deposit.c +++ b/c/src/pay/zksync/zk_deposit.c @@ -87,7 +87,7 @@ in3_ret_t zksync_deposit(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { sb_add_chars(sb, ",\"priorityOpId\":"); sb_add_int(sb, bytes_to_long(data->data + 64 - 8, 8)); sb_add_chars(sb, "}"); - req_remove_required(ctx->req, req_find_required(ctx->req, "eth_sendTransactionAndWait"), true); + req_remove_required(ctx->req, req_find_required(ctx->req, "eth_sendTransactionAndWait", NULL), true); return in3_rpc_handle_finish(ctx); } } diff --git a/c/src/pay/zksync/zk_helper.c b/c/src/pay/zksync/zk_helper.c index d4fa570dc..8a238984a 100644 --- a/c/src/pay/zksync/zk_helper.c +++ b/c/src/pay/zksync/zk_helper.c @@ -79,7 +79,7 @@ in3_ret_t send_provider_request(in3_req_t* parent, zksync_config_t* conf, char* in3 = alloca(strlen(conf->provider_url) + 26); sprintf(in3, "{\"rpc\":\"%s\"}", conf->provider_url); } - return req_send_sub_request(parent, method, params, in3, result); + return req_send_sub_request(parent, method, params, in3, result, NULL); } void zksync_calculate_account(address_t creator, bytes32_t codehash, bytes32_t saltarg, address_t pub_key_hash, address_t dst) { @@ -269,7 +269,7 @@ in3_ret_t zksync_get_contracts(zksync_config_t* conf, in3_req_t* ctx, uint8_t** } // clean up - req_remove_required(ctx, req_find_required(ctx, "contract_address"), false); + req_remove_required(ctx, req_find_required(ctx, "contract_address", NULL), false); } if (main) *main = conf->main_contract; @@ -364,7 +364,7 @@ in3_ret_t resolve_tokens(zksync_config_t* conf, in3_req_t* ctx, d_token_t* token } // clean up - req_remove_required(ctx, req_find_required(ctx, "tokens"), false); + req_remove_required(ctx, req_find_required(ctx, "tokens", NULL), false); if (cache_name) { bytes_t data = bytes((void*) conf->tokens, conf->token_len * sizeof(zksync_token_t)); diff --git a/c/src/pay/zksync/zk_message.c b/c/src/pay/zksync/zk_message.c index a370d425c..cc6efa11f 100644 --- a/c/src/pay/zksync/zk_message.c +++ b/c/src/pay/zksync/zk_message.c @@ -245,7 +245,7 @@ in3_ret_t zksync_sign(zksync_config_t* conf, bytes_t msg, in3_req_t* ctx, uint8_ p[msg.len * 2 + 3] = '"'; p[msg.len * 2 + 4] = 0; d_token_t* result; - TRY(req_send_sub_request(ctx, "zk_sign", p, NULL, &result)) + TRY(req_send_sub_request(ctx, "zk_sign", p, NULL, &result, NULL)) if (d_type(result) != T_BYTES || d_len(result) != 96) return req_set_error(ctx, "invalid signature returned", IN3_ECONFIG); memcpy(sig, result->data, 96); return IN3_OK; diff --git a/c/src/pay/zksync/zk_musig.c b/c/src/pay/zksync/zk_musig.c index e24ead148..6dd855fdf 100644 --- a/c/src/pay/zksync/zk_musig.c +++ b/c/src/pay/zksync/zk_musig.c @@ -43,7 +43,7 @@ static in3_ret_t send_sign_request(in3_req_t* parent, int pos, zksync_config_t* if (!url) return req_set_error(parent, "missing url to fetch a signature", IN3_EINVAL); char* in3 = alloca(strlen(url) + 26); sprintf(in3, "{\"rpc\":\"%s\"}", url); - return req_send_sub_request(parent, method, params, in3, result); + return req_send_sub_request(parent, method, params, in3, result, NULL); } static in3_ret_t update_session(zk_musig_session_t* s, in3_req_t* ctx, d_token_t* data) { @@ -162,6 +162,7 @@ static in3_ret_t verify_proof(zksync_config_t* conf, in3_req_t* ctx, bytes_t* ac if (!signer_key) return req_set_error(ctx, "the signer key could not be found!", IN3_EINVAL); d_token_t* result = NULL; + in3_req_t* sub = NULL; char* proof_data = d_create_json(ctx->request_context, proof); sb_t sb = {0}; sb_add_rawbytes(&sb, "\"0x", *msg, 0); @@ -171,10 +172,10 @@ static in3_ret_t verify_proof(zksync_config_t* conf, in3_req_t* ctx, bytes_t* ac sb_add_chars(&sb, proof_data); _free(proof_data); - TRY_FINAL(req_send_sub_request(ctx, conf->proof_verify_method, sb.data, NULL, &result), _free(sb.data)) + TRY_FINAL(req_send_sub_request(ctx, conf->proof_verify_method, sb.data, NULL, &result, &sub), _free(sb.data)) in3_ret_t ret = (d_type(result) == T_BOOLEAN && d_int(result)) ? IN3_OK : req_set_error(ctx, "Proof could not be verified!", IN3_EINVAL); - req_remove_required(ctx, req_find_required(ctx, conf->proof_verify_method), false); + req_remove_required(ctx, sub, false); return ret; } @@ -184,6 +185,7 @@ static in3_ret_t create_proof(zksync_config_t* conf, in3_req_t* ctx, bytes_t* ms // prepare the arguments to create the proof d_token_t* result = NULL; uint8_t* account; + in3_req_t* sub = NULL; TRY(zksync_get_account(conf, ctx, &account)) sb_t sb = {0}; sb_add_rawbytes(&sb, "\"0x", *msg, 0); @@ -191,14 +193,11 @@ static in3_ret_t create_proof(zksync_config_t* conf, in3_req_t* ctx, bytes_t* ms sb_add_chars(&sb, "\""); // send the subrequest and wait for a response - TRY_FINAL(req_send_sub_request(ctx, conf->proof_create_method, sb.data, NULL, &result), _free(sb.data)) + TRY_FINAL(req_send_sub_request(ctx, conf->proof_create_method, sb.data, NULL, &result, &sub), _free(sb.data)) // handle error if (!result) req_set_error(ctx, "Proof could not be created!", IN3_EINVAL); - // all is well, so we find the subrequest - in3_req_t* sub = req_find_required(ctx, conf->proof_create_method); - // only copy the data as json, so we can store them without a json_ctx and can clean up. if (sub) { *proof_data = d_create_json(sub->response_context, result); diff --git a/c/src/verifier/btc/btc_target.c b/c/src/verifier/btc/btc_target.c index b91367ee3..076719990 100644 --- a/c/src/verifier/btc/btc_target.c +++ b/c/src/verifier/btc/btc_target.c @@ -173,7 +173,7 @@ in3_ret_t btc_check_target(btc_target_conf_t* tc, in3_vctx_t* vc, uint32_t block if (block_number < BIP34_START) return IN3_OK; // for pre bip34, this finalityheader already checked it // is there a required ctx, which we need to clean up? - in3_req_t* ctx = req_find_required(vc->req, "btc_proofTarget"); // do we have an existing required proofTarget-request? + in3_req_t* ctx = req_find_required(vc->req, "btc_proofTarget", NULL); // do we have an existing required proofTarget-request? if (ctx) // yes, we do! switch (in3_req_state(ctx)) { // but what is the state? case REQ_ERROR: // there was an error, diff --git a/c/src/verifier/eth1/basic/eth_account.c b/c/src/verifier/eth1/basic/eth_account.c index 3e690729c..e621b5d49 100644 --- a/c/src/verifier/eth1/basic/eth_account.c +++ b/c/src/verifier/eth1/basic/eth_account.c @@ -50,7 +50,7 @@ static int is_not_existened(d_token_t* account) { d_token_t* t = NULL; return ((t = d_get(account, K_BALANCE)) && d_type(t) == T_INTEGER && d_int(t) == 0 && (t = d_getl(account, K_CODE_HASH, 32)) && memcmp(t->data, EMPTY_HASH, 32) == 0 && d_get_long(account, K_NONCE) == 0) && (t = d_getl(account, K_STORAGE_HASH, 32)) && memcmp(t->data, EMPTY_ROOT_HASH, 32) == 0; } - +const uint8_t* empty_hash() { return EMPTY_HASH; } static in3_ret_t verify_proof(in3_vctx_t* vc, bytes_t* header, d_token_t* account) { d_token_t * t, *storage_proof, *p; int i; diff --git a/c/src/verifier/eth1/basic/eth_basic.c b/c/src/verifier/eth1/basic/eth_basic.c index cc140b018..a83c2a567 100644 --- a/c/src/verifier/eth1/basic/eth_basic.c +++ b/c/src/verifier/eth1/basic/eth_basic.c @@ -101,8 +101,10 @@ static in3_ret_t eth_send_transaction_and_wait(in3_rpc_handle_ctx_t* ctx) { str_range_t r = d_to_json(ctx->params + 1); char* tx_data = alloca(r.len + 1); memcpy(tx_data, r.data, r.len); - tx_data[r.len] = 0; - TRY(req_send_sub_request(ctx->req, "eth_sendTransaction", tx_data, NULL, &tx_hash)) + tx_data[r.len] = 0; + in3_req_t* send_req = NULL; + in3_req_t* last_r = NULL; + TRY(req_send_sub_request(ctx->req, "eth_sendTransaction", tx_data, NULL, &tx_hash, &send_req)) // tx was sent, we have a tx_hash char tx_hash_hex[69]; bytes_to_hex(d_bytes(tx_hash)->data, 32, tx_hash_hex + 3); @@ -112,28 +114,27 @@ static in3_ret_t eth_send_transaction_and_wait(in3_rpc_handle_ctx_t* ctx) { tx_hash_hex[68] = 0; // get the tx_receipt - TRY(req_send_sub_request(ctx->req, "eth_getTransactionReceipt", tx_hash_hex, NULL, &tx_receipt)) + TRY(req_send_sub_request(ctx->req, "eth_getTransactionReceipt", tx_hash_hex, NULL, &tx_receipt, &last_r)) if (d_type(tx_receipt) == T_NULL || d_get_long(tx_receipt, K_BLOCK_NUMBER) == 0) { // no tx yet // we remove it and try again - in3_req_t* last_r = req_find_required(ctx->req, "eth_getTransactionReceipt"); - uint32_t wait = d_get_int(d_get(last_r->requests[0], K_IN3), K_WAIT); - wait = wait ? wait * 2 : 1000; + uint32_t wait = d_get_int(d_get(last_r->requests[0], K_IN3), K_WAIT); + wait = wait ? wait * 2 : 1000; req_remove_required(ctx->req, last_r, false); if (wait > 120000) // more than 2 minutes is too long, so we stop here return req_set_error(ctx->req, "Waited too long for the transaction to be minded", IN3_ELIMIT); char in3[20]; sprintf(in3, "{\"wait\":%d}", wait); - return req_send_sub_request(ctx->req, "eth_getTransactionReceipt", tx_hash_hex, in3, &tx_receipt); + return req_send_sub_request(ctx->req, "eth_getTransactionReceipt", tx_hash_hex, in3, &tx_receipt, &last_r); } else { // we have a result and we keep it str_range_t r = d_to_json(tx_receipt); sb_add_range(in3_rpc_handle_start(ctx), r.data, 0, r.len); - req_remove_required(ctx->req, req_find_required(ctx->req, "eth_getTransactionReceipt"), false); - req_remove_required(ctx->req, req_find_required(ctx->req, "eth_sendRawTransaction"), false); + req_remove_required(ctx->req, last_r, false); + req_remove_required(ctx->req, send_req, false); return in3_rpc_handle_finish(ctx); } } diff --git a/c/src/verifier/eth1/basic/eth_basic.h b/c/src/verifier/eth1/basic/eth_basic.h index 096b99184..ca556461b 100644 --- a/c/src/verifier/eth1/basic/eth_basic.h +++ b/c/src/verifier/eth1/basic/eth_basic.h @@ -135,6 +135,11 @@ in3_ret_t handle_eth_sendTransaction(in3_req_t* req, /**< the current contex d_token_t* req_data /**< the request */ ); +/** + * returns a pointer to 32 bytes marking a empty hash (keccakc(0x)) + */ +const uint8_t* empty_hash(); + /** * minimum signer for the wallet, returns the signed message which needs to be freed */ diff --git a/c/src/verifier/eth1/basic/filter.c b/c/src/verifier/eth1/basic/filter.c index 5b4514c23..12ef044c6 100644 --- a/c/src/verifier/eth1/basic/filter.c +++ b/c/src/verifier/eth1/basic/filter.c @@ -182,7 +182,7 @@ in3_ret_t filter_add(in3_filter_handler_t* filters, in3_req_t* ctx, in3_filter_t in3_ret_t res = IN3_OK; uint64_t current_block = 0; - in3_req_t* block_ctx = req_find_required(ctx, "eth_blockNumber"); + in3_req_t* block_ctx = req_find_required(ctx, "eth_blockNumber", NULL); if (!block_ctx) return req_add_required(ctx, req_new(ctx->client, _strdupn("{\"method\":\"eth_blockNumber\",\"params\":[]}", -1))); else { @@ -258,7 +258,7 @@ in3_ret_t filter_get_changes(in3_filter_handler_t* filters, in3_req_t* ctx, size return req_set_error(ctx, "filter with id does not exist", IN3_EUNKNOWN); // fetch the current block number - in3_req_t* block_ctx = req_find_required(ctx, "eth_blockNumber"); + in3_req_t* block_ctx = req_find_required(ctx, "eth_blockNumber", NULL); if (!block_ctx) return req_add_required(ctx, req_new(ctx->client, _strdupn("{\"method\":\"eth_blockNumber\",\"params\":[]}", -1))); else { @@ -288,7 +288,7 @@ in3_ret_t filter_get_changes(in3_filter_handler_t* filters, in3_req_t* ctx, size return IN3_OK; } - in3_req_t* logs_ctx = req_find_required(ctx, "eth_getLogs"); + in3_req_t* logs_ctx = req_find_required(ctx, "eth_getLogs", NULL); if (!logs_ctx) { // create request char* fopt_ = filter_opt_set_fromBlock(fopt, f->last_block, !f->is_first_usage); diff --git a/c/src/verifier/eth1/basic/sign_tx.c b/c/src/verifier/eth1/basic/sign_tx.c index 1c3bb5c5c..413cb8d3f 100644 --- a/c/src/verifier/eth1/basic/sign_tx.c +++ b/c/src/verifier/eth1/basic/sign_tx.c @@ -62,7 +62,7 @@ static inline bytes_t getl(d_token_t* t, uint16_t key, size_t l) { /** return data from the client.*/ static in3_ret_t get_from_nodes(in3_req_t* parent, char* method, char* params, bytes_t* dst) { // check if the method is already existing - in3_req_t* ctx = req_find_required(parent, method); + in3_req_t* ctx = req_find_required(parent, method, NULL); if (ctx) { // found one - so we check if it is useable. switch (in3_req_state(ctx)) { @@ -168,7 +168,7 @@ in3_ret_t eth_prepare_unsigned_tx(d_token_t* tx, in3_req_t* ctx, bytes_t* dst) { chain_id_t chain_id = ctx->client->chain.chain_id; if (chain_id == CHAIN_ID_LOCAL) { d_token_t* r = NULL; - TRY(req_send_sub_request(ctx, "eth_chainId", "", NULL, &r)) + TRY(req_send_sub_request(ctx, "eth_chainId", "", NULL, &r, NULL)) chain_id = d_long(r); } TRY(get_from_address(tx, ctx, from)) @@ -197,8 +197,8 @@ in3_ret_t eth_prepare_unsigned_tx(d_token_t* tx, in3_req_t* ctx, bytes_t* dst) { } // cleanup subcontexts - TRY(req_remove_required(ctx, req_find_required(ctx, "eth_getTransactionCount"), false)) - TRY(req_remove_required(ctx, req_find_required(ctx, "eth_gasPrice"), false)) + TRY(req_remove_required(ctx, req_find_required(ctx, "eth_getTransactionCount", NULL), false)) + TRY(req_remove_required(ctx, req_find_required(ctx, "eth_gasPrice", NULL), false)) return IN3_OK; } @@ -213,7 +213,7 @@ in3_ret_t eth_sign_raw_tx(bytes_t raw_tx, in3_req_t* ctx, address_t from, bytes_ chain_id_t chain_id = ctx->client->chain.chain_id; if (chain_id == CHAIN_ID_LOCAL) { d_token_t* r = NULL; - TRY(req_send_sub_request(ctx, "eth_chainId", "", NULL, &r)) + TRY(req_send_sub_request(ctx, "eth_chainId", "", NULL, &r, NULL)) chain_id = d_long(r); } @@ -268,7 +268,7 @@ in3_ret_t handle_eth_sendTransaction(in3_req_t* ctx, d_token_t* req) { // is there a pending signature? // we get the raw transaction from this request - in3_req_t* sig_ctx = req_find_required(ctx, "sign_ec_hash"); + in3_req_t* sig_ctx = req_find_required(ctx, "sign_ec_hash", NULL); if (sig_ctx) { bytes_t raw = *d_get_bytes_at(d_get(sig_ctx->requests[0], K_PARAMS), 0); unsigned_tx = bytes(_malloc(raw.len), raw.len); diff --git a/c/src/verifier/eth1/evm/accounts.c b/c/src/verifier/eth1/evm/accounts.c index acddf18fa..818ff7f1d 100644 --- a/c/src/verifier/eth1/evm/accounts.c +++ b/c/src/verifier/eth1/evm/accounts.c @@ -38,23 +38,26 @@ #include "big.h" #include "gas.h" #ifdef EVM_GAS -/** - * sets a variable value to 32byte word. - */ -account_t* evm_get_account(evm_t* evm, address_t adr, wlen_t create) { - if (!adr) return NULL; +int evm_get_account(evm_t* evm, address_t adr, wlen_t create, account_t** dst) { + if (!adr) { + *dst = NULL; + return 0; + } account_t* ac = evm->accounts; // check if we already have the account. while (ac) { - if (memcmp(ac->address, adr, 20) == 0) return ac; + if (memcmp(ac->address, adr, 20) == 0) { + *dst = ac; + return 0; + } ac = ac->next; } // if this is a internal call take it from the parent if (evm->parent) { - ac = evm_get_account(evm->parent, adr, create); + TRY(evm_get_account(evm->parent, adr, create, &ac)) if (ac) { // clone and add account @@ -63,7 +66,8 @@ account_t* evm_get_account(evm_t* evm, address_t adr, wlen_t create) { a->storage = NULL; a->next = evm->accounts; evm->accounts = a; - return a; + *dst = a; + return 0; } } @@ -73,9 +77,12 @@ account_t* evm_get_account(evm_t* evm, address_t adr, wlen_t create) { int l_code_size = evm->env(evm, EVM_ENV_CODE_SIZE, adr, 20, &code_size, 0, 0); int l_nonce = evm->env(evm, EVM_ENV_NONCE, adr, 20, &nonce, 0, 0); - if (l_balance >= 0) optimize_len(balance, l_balance); - if (l_nonce >= 0) optimize_len(nonce, l_nonce); - if (l_code_size >= 0) optimize_len(code_size, l_code_size); + if (l_balance < 0) return l_balance; + if (l_code_size < 0) return l_code_size; + if (l_nonce < 0) return l_nonce; + optimize_len(balance, l_balance); + optimize_len(code_size, l_code_size); + optimize_len(nonce, l_nonce); // is this a non-empty account? (or do we have to create one) if (create || l_balance > 1 || l_nonce > 1 || l_code_size > 1 || (l_balance == 1 && *balance) || (l_nonce == 1 && *nonce) || (l_code_size == 1 && *code_size)) { @@ -97,13 +104,17 @@ account_t* evm_get_account(evm_t* evm, address_t adr, wlen_t create) { uint256_set(balance, l_balance, ac->balance); uint256_set(nonce, l_nonce, ac->nonce); } - return ac; + + *dst = ac; + return 0; } -account_t* evm_create_account(evm_t* evm, uint8_t* data, uint32_t l_data, address_t code_address, address_t caller) { +int evm_create_account(evm_t* evm, uint8_t* data, uint32_t l_data, address_t code_address, address_t caller, account_t** dst) { - account_t* new_account = NULL; - new_account = evm_get_account(evm, code_address, 1); + account_t* sender_account = NULL; + account_t* new_account = NULL; + int r = evm_get_account(evm, code_address, 1, &new_account); + if (r < 0) return r; // this is a create-call evm->code = bytes(data, l_data); evm->call_data.len = 0; @@ -111,15 +122,21 @@ account_t* evm_create_account(evm_t* evm, uint8_t* data, uint32_t l_data, addres new_account->nonce[31] = 1; // increment the nonce of the sender - account_t* sender_account = evm_get_account(evm, caller, 1); - bytes32_t new_nonce; + r = evm_get_account(evm, caller, 1, &sender_account); + if (r < 0) return r; + bytes32_t new_nonce; increment_nonce(sender_account, new_nonce); - return new_account; + *dst = new_account; + return 0; } -storage_t* evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_key_len, wlen_t create) { - account_t* ac = evm_get_account(evm, adr, create); - if (!ac) return NULL; +int evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_key_len, wlen_t create, storage_t** dst) { + account_t* ac = NULL; + TRY(evm_get_account(evm, adr, create, &ac)); + if (!ac) { + *dst = NULL; + return 0; + } storage_t* s = ac->storage; @@ -129,20 +146,25 @@ storage_t* evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_k // find existing entry while (s) { - if (memcmp(s->key, key_data, 32) == 0) return s; + if (memcmp(s->key, key_data, 32) == 0) { + *dst = s; + return 0; + } s = s->next; } // not found?, but if we have parents, we try to copy the entry from there first if (evm->parent) { - storage_t* parent_s = evm_get_storage(evm->parent, adr, s_key, s_key_len, create); + storage_t* parent_s = NULL; + TRY(evm_get_storage(evm->parent, adr, s_key, s_key_len, create, &parent_s)); if (parent_s) { // clone and add account s = _malloc(sizeof(storage_t)); memcpy(s, parent_s, sizeof(storage_t)); s->next = ac->storage; ac->storage = s; - return s; + *dst = s; + return 0; } } @@ -152,6 +174,8 @@ storage_t* evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_k ? 0 : evm->env(evm, EVM_ENV_STORAGE, s_key, s_key_len, &data, 0, 0); + // if (l < 0) return l; + // if it does not exist and we have a value, we set it if (create || l > 1 || (l == 1 && *data)) { // create with key @@ -165,7 +189,8 @@ storage_t* evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_k // set the value uint256_set(data, l, s->value); } - return s; + *dst = s; + return 0; } void copy_state(evm_t* dst, evm_t* src) { @@ -259,16 +284,18 @@ void copy_state(evm_t* dst, evm_t* src) { /** * transfer a value to a account. */ -int transfer_value(evm_t* current, address_t from_account, address_t to_account, uint8_t* value, wlen_t value_len, uint32_t base_gas) { +int transfer_value(evm_t* current, address_t from_account, address_t to_account, uint8_t* value, wlen_t value_len, uint32_t base_gas, bool is_call) { if (big_is_zero(value, value_len)) return 0; // while the gas is handled by the parent, the new state is handled in the current evm, so we can roll it back. - evm_t* evm = current->parent ? current->parent : current; - - account_t* ac_from = evm_get_account(current, from_account, true); - account_t* ac_to = evm_get_account(current, to_account, false); + evm_t* evm = current->parent ? current->parent : current; + account_t* ac_from = NULL; + account_t* ac_to = NULL; uint8_t tmp[32], val[32]; + TRY(evm_get_account(current, from_account, true, &ac_from)) + TRY(evm_get_account(current, to_account, false, &ac_to)) + // we clone it because the value may point to the value we want to change. memcpy(val, value, value_len); value = val; @@ -276,13 +303,13 @@ int transfer_value(evm_t* current, address_t from_account, address_t to_account, if (!ac_to) { // to account does exist, so we create it and manage gas for new account subgas(G_NEWACCOUNT); - ac_to = evm_get_account(current, to_account, true); + TRY(evm_get_account(current, to_account, true, &ac_to)) } subgas(base_gas); if (ac_from) { // check if the balance of the sender is high enough - if (big_cmp(ac_from->balance, 32, value, value_len) < 0) return EVM_ERROR_BALANCE_TOO_LOW; + if (big_cmp(ac_from->balance, 32, value, value_len) < 0) return is_call ? 0 : EVM_ERROR_BALANCE_TOO_LOW; // sub balance from sender uint256_set(tmp, big_sub(ac_from->balance, 32, value, value_len, tmp), ac_from->balance); diff --git a/c/src/verifier/eth1/evm/accounts.h b/c/src/verifier/eth1/evm/accounts.h index e8f9a330b..cf47cd084 100644 --- a/c/src/verifier/eth1/evm/accounts.h +++ b/c/src/verifier/eth1/evm/accounts.h @@ -36,16 +36,15 @@ #include /** reads a account from the enviroment. */ -account_t* evm_get_account(evm_t* evm, address_t adr, wlen_t create); +int evm_get_account(evm_t* evm, address_t adr, wlen_t create, account_t** dst); /** get account storage */ -storage_t* evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_key_len, wlen_t create); +int evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_key_len, wlen_t create, storage_t** dst); +int evm_create_account(evm_t* evm, uint8_t* data, uint32_t l_data, address_t code_address, address_t caller, account_t** dst); /** copy state. */ void copy_state(evm_t* dst, evm_t* src); -int transfer_value(evm_t* current, address_t from_account, address_t to_account, uint8_t* value, wlen_t value_len, uint32_t base_gas); - -account_t* evm_create_account(evm_t* evm, uint8_t* data, uint32_t l_data, address_t code_address, address_t caller); +int transfer_value(evm_t* current, address_t from_account, address_t to_account, uint8_t* value, wlen_t value_len, uint32_t base_gas, bool is_call); void increment_nonce(account_t* ac, bytes32_t nonce_output); \ No newline at end of file diff --git a/c/src/verifier/eth1/evm/call.c b/c/src/verifier/eth1/evm/call.c index 2a4dc6ace..4d6816de7 100644 --- a/c/src/verifier/eth1/evm/call.c +++ b/c/src/verifier/eth1/evm/call.c @@ -33,6 +33,7 @@ *******************************************************************************/ #include "../../../core/client/plugin.h" +#include "../../../core/util/log.h" #include "../../../core/util/mem.h" #include "big.h" #include "evm.h" @@ -174,8 +175,9 @@ int evm_sub_call(evm_t* parent, UNUSED_VAR(gas); // create a new evm - evm_t evm; - int res = evm_prepare_evm(&evm, address, code_address, origin, caller, parent->env, parent->env_ptr, mode), success = 0; + evm_t evm; + int res = evm_prepare_evm(&evm, address, code_address, origin, caller, parent->env, parent->env_ptr, mode), success = 0; + if (res < 0) goto cleanup; uint32_t c_xfer = 0, old_gas = 0; #ifdef EVM_GAS @@ -248,12 +250,42 @@ int evm_sub_call(evm_t* parent, } } FINALIZE_SUBCALL_GAS(&evm, success, parent); + +cleanup: // clean up evm_free(&evm); // we always return 0 since a failure simply means we write a 0 on the stack. return res; } +#ifdef EVM_GAS + +static void add_log(json_ctx_t* receipt, int logs, logs_t* log, uint32_t* index) { + if (!log) return; + add_log(receipt, logs, log->next, index); + int l = json_create_object(receipt); + json_array_add_value(receipt, logs, receipt->result + l); + json_object_add_prop(receipt, l, key("transactionLogIndex"), json_create_int(receipt, *index)); + *index = *index + 1; + json_object_add_prop(receipt, l, key("address"), json_create_bytes(receipt, bytes(log->address, 20))); + json_object_add_prop(receipt, l, key("data"), json_create_bytes(receipt, log->data)); + int topics = json_create_array(receipt); + json_object_add_prop(receipt, l, key("topics"), receipt->result + topics); + + for (unsigned int i = 0; i < log->topics.len; i += 32) + json_array_add_value(receipt, topics, json_create_bytes(receipt, bytes(log->topics.data + i, 32))); +} + +static void add_receipt(evm_t* evm, json_ctx_t* receipt, uint64_t gas_used) { + int r = json_create_object(receipt); + json_object_add_prop(receipt, r, key("gasUsed"), json_create_int(receipt, gas_used)); + int logs = json_create_array(receipt); + json_object_add_prop(receipt, r, key("logs"), receipt->result + logs); + uint32_t log_index = 0; + add_log(receipt, logs, evm->logs, &log_index); +} +#endif + /** * run a evm-call */ @@ -261,10 +293,11 @@ int evm_call(void* vc, address_t address, uint8_t* value, wlen_t l_value, uint8_t* data, uint32_t l_data, - address_t caller, - uint64_t gas, - uint64_t chain_id, - bytes_t** result) { + address_t caller, + uint64_t gas, + uint64_t chain_id, + bytes_t** result, + json_ctx_t* receipt) { evm_t evm; int res = evm_prepare_evm(&evm, address, address, caller, caller, in3_get_env, vc, 0); @@ -277,7 +310,7 @@ int evm_call(void* vc, #ifdef EVM_GAS // we only transfer initial value if the we have caller - if (res == 0 && l > 1) res = transfer_value(&evm, caller, address, value, l_value, 0); + if (res == 0 && l > 1) res = transfer_value(&evm, caller, address, value, l_value, 0, true); #else UNUSED_VAR(gas); UNUSED_VAR(value); @@ -288,11 +321,21 @@ int evm_call(void* vc, #ifdef EVM_GAS evm.gas = gas; #endif - evm.call_data.data = data; - evm.call_data.len = l_data; + evm.call_value.data = value; + evm.call_value.len = l_value; + evm.call_data.data = data; + evm.call_data.len = l_data; if (res == 0) res = evm_run(&evm, address); if (res == 0 && evm.return_data.data) *result = b_dup(&evm.return_data); + +#ifdef EVM_GAS + if (receipt) + add_receipt(&evm, receipt, gas - evm.gas); +#else + UNUSED_VAR(receipt); +#endif + evm_free(&evm); return res; diff --git a/c/src/verifier/eth1/evm/evm.c b/c/src/verifier/eth1/evm/evm.c index 21c1bd9c9..32e16fd15 100644 --- a/c/src/verifier/eth1/evm/evm.c +++ b/c/src/verifier/eth1/evm/evm.c @@ -37,6 +37,7 @@ #include "../../../core/util/data.h" #include "../../../core/util/log.h" #include "../../../core/util/mem.h" +#include "../../../core/util/utils.h" #include "../../../third-party/crypto/bignum.h" #include "../nano/merkle.h" #include "../nano/serialize.h" @@ -516,8 +517,9 @@ int evm_run(evm_t* evm, address_t code_address) { // subtract gas cost for ceation transactions subgas(evm->return_data.len * G_CODEDEPOSIT); // Modify state - account_t* acc_adr = evm_get_account(evm, evm->account, true); - acc_adr->code = evm->return_data; + account_t* acc_adr = NULL; + TRY(evm_get_account(evm, evm->account, true, &acc_adr)) + acc_adr->code = evm->return_data; } } // debug gas output diff --git a/c/src/verifier/eth1/evm/evm.h b/c/src/verifier/eth1/evm/evm.h index 1482dc33e..53322168d 100644 --- a/c/src/verifier/eth1/evm/evm.h +++ b/c/src/verifier/eth1/evm/evm.h @@ -37,6 +37,7 @@ * */ #include "../../../core/util/bytes.h" +#include "../../../core/util/data.h" #ifndef evm_h__ #define evm_h__ int exit_zero(void); @@ -84,7 +85,7 @@ typedef enum evm_state { #define EVM_PROP_ISTANBUL 32 #define EVM_PROP_NO_FINALIZE 32768 #define EVM_PROP_STATIC 256 -#define EVM_PROP_TXCREATE 512 /**< executing a creation transaction > */ +#define EVM_PROP_TXCREATE 512 /**< executing a creation transaction > */ #define EVM_PROP_CALL_DEPEND_ON_REFUND 1024 /**< executing code that depends on subcall gas refund to succeed > */ #define EVM_ENV_BALANCE 1 @@ -125,31 +126,34 @@ typedef enum evm_state { #define OP_EXTCODECOPY_GAS(evm) \ do { \ - account_t* ac = evm_get_account(evm, address, 0); \ + account_t* ac = NULL; \ + TRY(evm_get_account(evm, address, 0, &ac)) \ if (ac && ac->code.len) \ return evm_mem_write(evm, mem_pos, bytes(ac->code.data + code_pos, ac->code.len > (uint32_t) code_pos ? ac->code.len - code_pos : 0), data_len); \ } while (0) -#define OP_SLOAD_GAS(evm) \ - do { \ - storage_t* s = evm_get_storage(evm, evm->account, key, l, 0); \ - if (s) { \ - value = s->value; \ - l = 32; \ - while (value[0] == 0 && l > 1) { \ - l--; \ - value++; \ - } \ - return evm_stack_push(evm, value, l); \ - } \ +#define OP_SLOAD_GAS(evm) \ + do { \ + storage_t* s = NULL; \ + TRY(evm_get_storage(evm, evm->account, key, l, 0, &s)) \ + if (s) { \ + value = s->value; \ + l = 32; \ + while (value[0] == 0 && l > 1) { \ + l--; \ + value++; \ + } \ + return evm_stack_push(evm, value, l); \ + } \ } while (0) #define OP_ACCOUNT_GAS(evm, key, address, data, l) \ do { \ if (key != EVM_ENV_BLOCKHASH) { \ - account_t* ac = evm_get_account(evm, address, 0); \ - uint8_t tmp[4]; \ - uint8_t hash[32]; \ + account_t* ac = NULL; \ + TRY(evm_get_account(evm, address, 0, &ac)) \ + uint8_t tmp[4]; \ + uint8_t hash[32]; \ if (ac) { \ data = NULL; \ if (key == EVM_ENV_BALANCE) { \ @@ -218,6 +222,7 @@ typedef struct account_storage { typedef struct logs { bytes_t topics; bytes_t data; + address_t address; struct logs* next; } logs_t; @@ -297,10 +302,11 @@ int evm_call(void* vc, uint8_t address[20], uint8_t* value, wlen_t l_value, uint8_t* data, uint32_t l_data, - uint8_t caller[20], - uint64_t gas, - uint64_t chain_id, - bytes_t** result); + uint8_t caller[20], + uint64_t gas, + uint64_t chain_id, + bytes_t** result, + json_ctx_t* receipt); void evm_print_stack(evm_t* evm, uint64_t last_gas, uint32_t pos); void evm_free(evm_t* evm); @@ -309,9 +315,9 @@ int evm_execute(evm_t* evm); int evm_run(evm_t* evm, address_t code_address); #ifdef EVM_GAS -account_t* evm_get_account(evm_t* evm, uint8_t adr[20], wlen_t create); -storage_t* evm_get_storage(evm_t* evm, uint8_t adr[20], uint8_t* key, wlen_t keylen, wlen_t create); -int transfer_value(evm_t* evm, uint8_t from_account[20], uint8_t to_account[20], uint8_t* value, wlen_t value_len, uint32_t base_gas); +int evm_get_account(evm_t* evm, address_t adr, wlen_t create, account_t** dst); +int evm_get_storage(evm_t* evm, address_t adr, uint8_t* s_key, wlen_t s_key_len, wlen_t create, storage_t** dst); +int transfer_value(evm_t* evm, uint8_t from_account[20], uint8_t to_account[20], uint8_t* value, wlen_t value_len, uint32_t base_gas, bool is_call); #endif #endif \ No newline at end of file diff --git a/c/src/verifier/eth1/evm/gas.h b/c/src/verifier/eth1/evm/gas.h index 101d54be2..e80675061 100644 --- a/c/src/verifier/eth1/evm/gas.h +++ b/c/src/verifier/eth1/evm/gas.h @@ -142,69 +142,70 @@ void update_account_code(evm_t* evm, account_t* new_account); #define SUBGAS(evm, g) subgas(evm, g) #define KEEP_TRACK_GAS(evm) evm->gas #define FINALIZE_SUBCALL_GAS(evm, success, parent) finalize_subcall_gas(evm, success, parent) -#define UPDATE_SUBCALL_GAS(evm, parent, address, code_address, caller, gas, mode, value, l_value) \ - do { \ - /**************************************************************/ \ - /* According to the Yellow Paper: C_call = C_gascap + C_extra */ \ - /* Where: */ \ - /* C_gascap = min(L(parent.gas - C_extra), gas) */ \ - /* L(x) = x - (x/64) */ \ - /* C_extra = G_CALL + C_xfer + C_new */ \ - /* C_xfer = (value == 0) ? 0 : G_CALLVALUE */ \ - /* C_new = to_account ? 0 : G_NEWACCOUNT */ \ - /**************************************************************/ \ - bool no_address = false; \ - if (!address) { \ - /* Flag EVM with "creating transaction", so the gas for modifying state will be deduced later */ \ - evm.properties |= EVM_PROP_TXCREATE; \ - new_account = evm_create_account(&evm, evm.call_data.data, evm.call_data.len, code_address, caller); \ - no_address = true; \ - } \ - else { /* if no code was already set for execution */ \ - account_t* ac = evm_get_account(parent, code_address, 0); \ - if (ac) evm.code = ac->code; \ - } \ - if (res == 0 && !big_is_zero(value, l_value)) { \ - if (mode == EVM_CALL_MODE_STATIC) \ - res = EVM_ERROR_UNSUPPORTED_CALL_OPCODE; \ - else { \ - if (mode == EVM_CALL_MODE_CALL || mode == EVM_CALL_MODE_CALLCODE) { \ - evm.gas += G_CALLSTIPEND; \ - c_xfer = G_CALLVALUE; \ - } \ - /* Transfer value from caller and deduce (C_xfer + C_new) from parent gas*/ \ - res = transfer_value(&evm, parent->address, evm.address, value, l_value, c_xfer); \ - } \ - } \ - /* Calculate L(parent.gas - C_extra) */ \ - /* As C_extra was already deduced in previous steps, we calculate only L(parent.gas) now */ \ - uint64_t max_gas_provided = parent->gas - (parent->gas >> 6); \ - /* Calculate C_gascap */ \ - if (no_address) { \ - gas = max_gas_provided; \ - } \ - else \ - gas = min(gas, max_gas_provided); \ - /* Assign values to child EVM */ \ - evm.gas += gas; \ - evm.init_gas = gas; \ - evm.gas_price.data = parent->gas_price.data; \ - evm.gas_price.len = parent->gas_price.len; \ - if (res == 0) { \ - if (parent->gas < gas) { \ - if (parent->gas + c_xfer < gas) { \ - /* transaction does not have enough gas to be completed */ \ - res = EVM_ERROR_OUT_OF_GAS; \ - } \ - else { \ - /* the call depends on how much gas will be refunded after execution to complete successfully */ \ - /* We take an 'optimistic' approach, set the flag and proceed with execution */ \ - evm.properties |= EVM_PROP_CALL_DEPEND_ON_REFUND; \ - } \ - } \ - else \ - parent->gas -= gas; \ - } \ +#define UPDATE_SUBCALL_GAS(evm, parent, address, code_address, caller, gas, mode, value, l_value) \ + do { \ + /**************************************************************/ \ + /* According to the Yellow Paper: C_call = C_gascap + C_extra */ \ + /* Where: */ \ + /* C_gascap = min(L(parent.gas - C_extra), gas) */ \ + /* L(x) = x - (x/64) */ \ + /* C_extra = G_CALL + C_xfer + C_new */ \ + /* C_xfer = (value == 0) ? 0 : G_CALLVALUE */ \ + /* C_new = to_account ? 0 : G_NEWACCOUNT */ \ + /**************************************************************/ \ + bool no_address = false; \ + if (!address) { \ + /* Flag EVM with "creating transaction", so the gas for modifying state will be deduced later */ \ + evm.properties |= EVM_PROP_TXCREATE; \ + res = evm_create_account(&evm, evm.call_data.data, evm.call_data.len, code_address, caller, &new_account); \ + no_address = true; \ + } \ + else { /* if no code was already set for execution */ \ + account_t* ac = NULL; \ + res = evm_get_account(parent, code_address, 0, &ac); \ + if (res == 0 && ac) evm.code = ac->code; \ + } \ + if (res == 0 && !big_is_zero(value, l_value)) { \ + if (mode == EVM_CALL_MODE_STATIC) \ + res = EVM_ERROR_UNSUPPORTED_CALL_OPCODE; \ + else { \ + if (mode == EVM_CALL_MODE_CALL || mode == EVM_CALL_MODE_CALLCODE) { \ + evm.gas += G_CALLSTIPEND; \ + c_xfer = G_CALLVALUE; \ + } \ + /* Transfer value from caller and deduce (C_xfer + C_new) from parent gas*/ \ + res = transfer_value(&evm, parent->address, evm.address, value, l_value, c_xfer, false); \ + } \ + } \ + /* Calculate L(parent.gas - C_extra) */ \ + /* As C_extra was already deduced in previous steps, we calculate only L(parent.gas) now */ \ + uint64_t max_gas_provided = parent->gas - (parent->gas >> 6); \ + /* Calculate C_gascap */ \ + if (no_address) { \ + gas = max_gas_provided; \ + } \ + else \ + gas = min(gas, max_gas_provided); \ + /* Assign values to child EVM */ \ + evm.gas += gas; \ + evm.init_gas = gas; \ + evm.gas_price.data = parent->gas_price.data; \ + evm.gas_price.len = parent->gas_price.len; \ + if (res == 0) { \ + if (parent->gas < gas) { \ + if (parent->gas + c_xfer < gas) { \ + /* transaction does not have enough gas to be completed */ \ + res = EVM_ERROR_OUT_OF_GAS; \ + } \ + else { \ + /* the call depends on how much gas will be refunded after execution to complete successfully */ \ + /* We take an 'optimistic' approach, set the flag and proceed with execution */ \ + evm.properties |= EVM_PROP_CALL_DEPEND_ON_REFUND; \ + } \ + } \ + else \ + parent->gas -= gas; \ + } \ } while (0) #define FINALIZE_AND_REFUND_GAS(evm) finalize_and_refund_gas(evm) diff --git a/c/src/verifier/eth1/evm/opcodes.c b/c/src/verifier/eth1/evm/opcodes.c index 8a9aa356a..550eaba67 100644 --- a/c/src/verifier/eth1/evm/opcodes.c +++ b/c/src/verifier/eth1/evm/opcodes.c @@ -599,7 +599,9 @@ int op_create(evm_t* evm, uint_fast8_t use_salt) { if (use_salt == 0) { // calculate the generated address - uint8_t* nonce = evm_get_account(evm, evm->address, true)->nonce; + account_t* ac = NULL; + TRY(evm_get_account(evm, evm->address, true, &ac)) + uint8_t* nonce = ac->nonce; bytes_builder_t* bb = bb_new(); tmp = bytes(evm->address, 20); rlp_encode_item(bb, &tmp); @@ -629,8 +631,9 @@ int op_create(evm_t* evm, uint_fast8_t use_salt) { } // get nonce before the call - account_t* ac = evm_get_account(evm, evm->address, 0); - uint8_t prev_nonce = ac->nonce[31]; + account_t* ac = NULL; + TRY(evm_get_account(evm, evm->address, 0, &ac)) + uint8_t prev_nonce = ac->nonce[31]; // now execute the call int res = evm_sub_call(evm, NULL, hash + 12, value, l_value, in_data.data, in_data.len, evm->address, evm->origin, 0, 0, 0, 0); @@ -645,7 +648,8 @@ int op_create(evm_t* evm, uint_fast8_t use_salt) { int op_selfdestruct(evm_t* evm) { uint8_t adr[20], l, *p; if (evm_stack_pop(evm, adr, 20) < 0) return EVM_ERROR_EMPTY_STACK; - account_t* self_account = evm_get_account(evm, evm->address, 1); + account_t *self_account = NULL, *tmp; + TRY(evm_get_account(evm, evm->address, 1, &self_account)) // TODO check if this account was selfsdesstructed before evm->refund += R_SELFDESTRUCT; @@ -653,11 +657,13 @@ int op_selfdestruct(evm_t* evm) { p = self_account->balance; optimize_len(p, l); if (l && (l > 1 || *p != 0)) { - if (evm_get_account(evm, adr, 0) == NULL) { + TRY(evm_get_account(evm, adr, 0, &tmp)) + + if (tmp == NULL) { if ((evm->properties & EVM_PROP_NO_FINALIZE) == 0) subgas(G_NEWACCOUNT); - evm_get_account(evm, adr, 1); + TRY(evm_get_account(evm, adr, 1, &tmp)) } - if (transfer_value(evm, evm->address, adr, self_account->balance, 32, 0) < 0) return EVM_ERROR_OUT_OF_GAS; + TRY(transfer_value(evm, evm->address, adr, self_account->balance, 32, 0, false)) } memset(self_account->balance, 0, 32); memset(self_account->nonce, 0, 32); @@ -680,19 +686,19 @@ int op_log(evm_t* evm, uint8_t len) { if (memlen) TRY(mem_check(evm, memoffset + memlen, true)); - logs_t* log = _malloc(sizeof(logs_t)); - - log->next = evm->logs; - evm->logs = log; - log->data.data = _malloc(memlen); - log->data.len = memlen; - - evm_mem_readi(evm, memoffset, log->data.data, memlen); - log->topics.data = _malloc(len * 32); - log->topics.len = len * 32; - uint8_t* t = NULL; int l; + logs_t* log = _malloc(sizeof(logs_t)); + evm_t* parent = evm; + while (parent->parent) parent = parent->parent; + log->next = parent->logs; + evm->logs = log; + log->data.data = _malloc(memlen); + log->data.len = memlen; + log->topics.data = _malloc(len * 32); + log->topics.len = len * 32; + memcpy(log->address, evm->address, 20); + evm_mem_readi(evm, memoffset, log->data.data, memlen); for (int i = 0; i < len; i++) { if ((l = evm_stack_pop_ref(evm, &t)) < 0) return l; @@ -707,11 +713,12 @@ int op_sstore(evm_t* evm) { if ((l_key = evm_stack_pop_ref(evm, &key)) < 0) return l_key; if ((l_val = evm_stack_pop_ref(evm, &value)) < 0) return l_val; - storage_t* s = evm_get_storage(evm, evm->account, key, l_key, 0); - uint8_t created = s == NULL, el = l_val; - uint8_t l_current = 0; + storage_t* s = NULL; + TRY(evm_get_storage(evm, evm->account, key, l_key, 0, &s)) + uint8_t created = s == NULL, el = l_val; + uint8_t l_current = 0; if (created) - s = evm_get_storage(evm, evm->account, key, l_key, 1); + TRY(evm_get_storage(evm, evm->account, key, l_key, 1, &s)) else { created = true; for (int i = 0; i < 32; i++) { diff --git a/c/src/verifier/eth1/full/eth_full.c b/c/src/verifier/eth1/full/eth_full.c index 1e33787ef..b075ad197 100644 --- a/c/src/verifier/eth1/full/eth_full.c +++ b/c/src/verifier/eth1/full/eth_full.c @@ -65,7 +65,7 @@ in3_ret_t in3_verify_eth_full(void* pdata, in3_plugin_act_t action, void* pctx) bytes_t* from = d_get_byteskl(tx, K_FROM, 20); bytes_t* value = d_get_bytes(tx, K_VALUE); bytes_t* data = d_get_bytes(tx, K_DATA); - bytes_t gas = d_to_bytes(d_get(tx, K_GAS_LIMIT)); + bytes_t gas = d_to_bytes(d_get_or(tx, K_GAS_LIMIT, K_GAS)); bytes_t* result = NULL; uint64_t gas_limit = bytes_to_long(gas.data, gas.len); if (!gas_limit) gas_limit = 0xFFFFFFFFFFFFFF; @@ -74,8 +74,16 @@ in3_ret_t in3_verify_eth_full(void* pdata, in3_plugin_act_t action, void* pctx) in3_log_disable_prefix(); in3_log_set_level(LOG_ERROR); #endif + // is there a receipt-context we need to pass? + json_ctx_t* receipt = NULL; + for (cache_entry_t* ce = vc->req->cache; ce; ce = ce->next) { + if (ce->props & CACHE_PROP_JSON) { + receipt = (json_ctx_t*) (void*) ce->value.data; + break; + } + } - int ret = evm_call(vc, address ? address->data : zeros, value ? value->data : zeros, value ? value->len : 1, data ? data->data : zeros, data ? data->len : 0, from ? from->data : zeros, gas_limit, vc->chain->chain_id, &result); + int ret = evm_call(vc, address ? address->data : zeros, value ? value->data : zeros, value ? value->len : 1, data ? data->data : zeros, data ? data->len : 0, from ? from->data : zeros, gas_limit, vc->chain->chain_id, &result, receipt); #if defined(DEBUG) && defined(LOGGING) in3_log_set_level(old); in3_log_enable_prefix(); @@ -102,8 +110,10 @@ in3_ret_t in3_verify_eth_full(void* pdata, in3_plugin_act_t action, void* pctx) return vc_err(vc, "This op code is not supported with eth_call!"); case EVM_ERROR_OUT_OF_GAS: return vc_err(vc, "Ran out of gas."); + case EVM_ERROR_BALANCE_TOO_LOW: + return vc_err(vc, "not enough funds to transfer the requested value."); case 0: - if (!result) return vc_err(vc, "no result"); + if (!result) return d_len(vc->result) == 0 ? 0 : vc_err(vc, "no result"); res = b_cmp(d_bytes(vc->result), result); b_free(result); diff --git a/c/src/verifier/eth1/nano/eth_nano.c b/c/src/verifier/eth1/nano/eth_nano.c index 1d6c80322..a147609e8 100644 --- a/c/src/verifier/eth1/nano/eth_nano.c +++ b/c/src/verifier/eth1/nano/eth_nano.c @@ -43,8 +43,8 @@ #include // list of methods allowed withoput proof -#define MAX_METHODS 25 -char* ALLOWED_METHODS[MAX_METHODS] = {"eth_chainId", "in3_stats", "eth_blockNumber", "web3_clientVersion", "web3_sha3", "net_version", "net_peerCount", "net_listening", "eth_protocolVersion", "eth_syncing", "eth_coinbase", "eth_mining", "eth_hashrate", "eth_gasPrice", "eth_accounts", "eth_sign", "eth_sendRawTransaction", "eth_estimateGas", "eth_getCompilers", "eth_compileLLL", "eth_compileSolidity", "eth_compileSerpent", "eth_getWork", "eth_submitWork", "eth_submitHashrate"}; +#define MAX_METHODS 26 +const char* ALLOWED_METHODS[MAX_METHODS] = {"eth_chainId", "in3_stats", "eth_blockNumber", "web3_clientVersion", "web3_sha3", "net_version", "net_peerCount", "net_listening", "eth_protocolVersion", "eth_syncing", "eth_coinbase", "eth_mining", "eth_hashrate", "eth_gasPrice", "eth_accounts", "eth_sign", "eth_sendRawTransaction", "eth_estimateGas", "eth_getCompilers", "eth_compileLLL", "eth_compileSolidity", "eth_compileSerpent", "eth_getWork", "eth_submitWork", "eth_submitHashrate", "eth_getProof"}; in3_ret_t in3_verify_eth_nano(void* p_data, in3_plugin_act_t action, void* pctx) { UNUSED_VAR(p_data); diff --git a/c/test/test_evm.c b/c/test/test_evm.c index a079012c8..38cff3391 100644 --- a/c/test/test_evm.c +++ b/c/test/test_evm.c @@ -219,7 +219,8 @@ int check_post_state(evm_t* evm, d_token_t* post) { uint8_t s_key[32]; int l_key = hex_to_bytes(s_str + 2, strlen(s_str) - 2, s_key, 32); bytes_t val_must = d_to_bytes(s); - storage_t* st = evm_get_storage(evm, address, s_key, l_key, 0); + storage_t* st = NULL; + TRY(evm_get_storage(evm, address, s_key, l_key, 0, &st)) if (!st) { print_error("Missing the storage key!"); return -1; @@ -340,6 +341,7 @@ int generate_state_root(evm_t* evm, uint8_t* dst) { uint8_t hash[32]; bytes_t hash_bytes = {.data = hash, .len = 32}; d_token_t* test = (d_token_t*) evm->env_ptr; + account_t* tmp; #ifdef EVM_GAS // make sure we have all accounts d_token_t *accounts = d_get(test, ikey(jc, "pre")), *t; @@ -347,7 +349,7 @@ int generate_state_root(evm_t* evm, uint8_t* dst) { for (i = 0, t = accounts + 1; i < d_len(accounts); i++, t = d_next(t)) { uint8_t adr[20]; hex_to_bytes(d_get_keystr(jc, t->key) + 2, 40, adr, 20); - evm_get_account(evm, adr, 1); + TRY(evm_get_account(evm, adr, 1, &tmp)) } EVM_DEBUG_BLOCK({ in3_log_trace("\n::: ================ "); @@ -397,19 +399,21 @@ static void uint256_setb(uint8_t* dst, uint8_t* data, int len) { #ifdef EVM_GAS static void read_accounts(evm_t* evm, d_token_t* accounts) { int i, j; + account_t* tmp = NULL; + storage_t* st = NULL; d_token_t *t, *storage, *s; for (i = 0, t = accounts + 1; i < d_len(accounts); i++, t = d_next(t)) { char* adr_str = d_get_keystr(jc, t->key); uint8_t address[20]; hex_to_bytes(adr_str + 2, strlen(adr_str) - 2, address, 20); - evm_get_account(evm, address, true); + evm_get_account(evm, address, true, &tmp); storage = d_get(t, ikey(jc, "storage")); if (storage) { for (j = 0, s = storage + 1; j < d_len(storage); j++, s = d_next(s)) { char* k = d_get_keystr(jc, s->key); uint8_t kk[32]; hex_to_bytes(k + 2, strlen(k) - 2, kk, 32); - evm_get_storage(evm, address, kk, (strlen(k) - 1) / 2, true); + evm_get_storage(evm, address, kk, (strlen(k) - 1) / 2, true, &st); } } } @@ -541,9 +545,11 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha // we need to create an account since we don't have one if (big_is_zero(evm.address, 20)) { + account_t* atmp = NULL; // calculate the generated address - uint8_t* nonce = evm_get_account(&evm, caller, true)->nonce; + TRY(evm_get_account(&evm, caller, true, &atmp)) + uint8_t* nonce = atmp->nonce; bytes_builder_t* bb = bb_new(); bytes_t tmp = bytes(caller, 20); bytes32_t hash; @@ -561,11 +567,13 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha bb_free(bb); memcpy(_to, hash + 12, 20); - evm_get_account(&evm, _to, true)->nonce[31]++; + TRY(evm_get_account(&evm, _to, true, &atmp)) + atmp->nonce[31]++; } // increase the nonce and pay for gas - account_t* c_adr = evm_get_account(&evm, evm.caller, true); + account_t* c_adr = NULL; + TRY(evm_get_account(&evm, evm.caller, true, &c_adr)) uint256_setn(c_adr->nonce, bytes_to_long(c_adr->nonce, 32) + 1); uint8_t tmp[32], txval[64]; int l; @@ -583,7 +591,8 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha uint256_setb(c_adr->balance, txval, l); // handle balance for receiver - account_t* to_adr = evm_get_account(&evm, evm.address, true); + account_t* to_adr = NULL; + TRY(evm_get_account(&evm, evm.address, true, &to_adr)) uint256_setb(to_adr->balance, tmp, big_add(to_adr->balance, 32, evm.call_value.data, evm.call_value.len, tmp, 32)); total_gas = tx_intrinsic_gas; @@ -634,7 +643,8 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha read_accounts(&evm, d_get(test, ikey(jc, "pre"))); // reduce the gasLimit*price from caller the - account_t* sender = evm_get_account(&evm, evm.caller, true); + account_t* sender = NULL; + TRY(evm_get_account(&evm, evm.caller, true, &sender)) long_to_bytes(total_gas, gas_tmp); int l = big_mul(evm.gas_price.data, evm.gas_price.len, gas_tmp, 8, gas_tmp2, 32); uint256_setb(sender->balance, gas_tmp, big_sub(sender->balance, 32, gas_tmp2, l, gas_tmp)); @@ -648,7 +658,8 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha // if there is gas left we return it to the sender if (evm.gas > 0) { - account_t* c_adr = evm_get_account(&evm, evm.caller, true); + account_t* c_adr = NULL; + TRY(evm_get_account(&evm, evm.caller, true, &c_adr)) long_to_bytes(evm.gas, tmp); l = big_mul(evm.gas_price.data, evm.gas_price.len, tmp, 8, tmp2, 32); l = big_add(tmp2, l, c_adr->balance, 32, tmp, 32); @@ -656,7 +667,8 @@ int run_evm(json_ctx_t* jctx, d_token_t* test, uint32_t props, uint64_t* ms, cha } // pay the miner the total gas - account_t* miner = evm_get_account(&evm, d_get_bytes(d_get(test, ikey(jc, "env")), ikey(jc, "currentCoinbase"))->data, 1); + account_t* miner = NULL; + TRY(evm_get_account(&evm, d_get_bytes(d_get(test, ikey(jc, "env")), ikey(jc, "currentCoinbase"))->data, 1, &miner)) // increase balance of the miner long_to_bytes(total_gas, tmp); diff --git a/c/test/unit_tests/test_core.c b/c/test/unit_tests/test_core.c index e543948db..d80981d4c 100644 --- a/c/test/unit_tests/test_core.c +++ b/c/test/unit_tests/test_core.c @@ -131,15 +131,15 @@ void test_str_replace() { } void test_json() { - char* data = "abc"; - json_ctx_t* json = json_create(); - json->result = json_create_array(json); - json_array_add_value(json->result, json_create_bool(json, true)); - json_object_add_prop(json->result, key("key"), json_create_null(json)); - json_array_add_value(json->result, json_create_object(json)); - json_array_add_value(json->result, json_create_bytes(json, bytes((uint8_t*) data, 3))); - json_array_add_value(json->result, json_create_string(json, data, -1)); - json_array_add_value(json->result, json_create_int(json, 10)); + char* data = "abc"; + json_ctx_t* json = json_create(); + int array = json_create_array(json); + json_array_add_value(json, array, json_create_bool(json, true)); + json_object_add_prop(json, array, key("key"), json_create_null(json)); + json_array_add_value(json, array, json->result + json_create_object(json)); + json_array_add_value(json, array, json_create_bytes(json, bytes((uint8_t*) data, 3))); + json_array_add_value(json, array, json_create_string(json, data, -1)); + json_array_add_value(json, array, json_create_int(json, 10)); char* jdata = d_create_json(json, json->result); TEST_ASSERT_EQUAL_STRING("[true,null,{},\"0x616263\",\"abc\",\"0xa\"]", jdata); free(jdata); diff --git a/python/tests/integrated/negative/client_test.py b/python/tests/integrated/negative/client_test.py index 9d4fa096a..7d07fdb07 100644 --- a/python/tests/integrated/negative/client_test.py +++ b/python/tests/integrated/negative/client_test.py @@ -40,11 +40,6 @@ def test_ens_address(self): with self.assertRaises(in3.ClientException): self.client.ens_owner('deprazz.eth') - def test_ens_namehash(self): - for i in range(50): - with self.assertRaises(in3.ClientException): - self.client.ens_namehash('0x0.eth') - class ClientParsingTest(unittest.TestCase): diff --git a/scripts/build_multi_wasm.sh b/scripts/build_multi_wasm.sh index 2dfc9da81..cb01ba469 100755 --- a/scripts/build_multi_wasm.sh +++ b/scripts/build_multi_wasm.sh @@ -1,4 +1,7 @@ #!/bin/bash +# exit if a command fails +set -e + function build { NAME=$1 OPTIONS=$2 @@ -28,7 +31,7 @@ function build { } # define options -source ~/ws/tools/emsdk/emsdk_env.sh > /dev/null +source ~/ws/tools/emsdk/emsdk_env.sh > /dev/null || echo "env should be set first" CWD=$PWD cd $(dirname $0)/.. DST="$CWD/$1" From 4fe8e012a51d7e8a573f7cbfd0d4b8dbeaddc49f Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 21 Mar 2021 08:52:07 +0100 Subject: [PATCH 003/221] fix --- c/include/in3/bytes.h | 6 ++++++ c/include/in3/data.h | 8 ++++---- c/include/in3/eth_api.h | 1 + c/include/in3/request.h | 10 ++++++---- c/include/in3/scache.h | 1 + c/include/in3/stringbuilder.h | 4 ++-- c/include/in3/utils.h | 5 +++++ c/src/cmd/in3/main.c | 2 +- 8 files changed, 26 insertions(+), 11 deletions(-) diff --git a/c/include/in3/bytes.h b/c/include/in3/bytes.h index de07d151f..0aa9fe3a1 100644 --- a/c/include/in3/bytes.h +++ b/c/include/in3/bytes.h @@ -123,6 +123,12 @@ NONULL static inline void b_optimize_len(bytes_t* b) { } } +static inline int b_compare(bytes_t a, bytes_t b) { + return (a.len == b.len) + ? memcmp(a.data, b.data, a.len) + : ((int) a.len) - ((int) b.len); +} + #define b_to_stack(d) \ { \ bytes_t o = d; \ diff --git a/c/include/in3/data.h b/c/include/in3/data.h index 016a41daa..1f9126a4e 100644 --- a/c/include/in3/data.h +++ b/c/include/in3/data.h @@ -151,10 +151,10 @@ NONULL d_token_t* json_create_bool(json_ctx_t* jp, bool value); NONULL d_token_t* json_create_int(json_ctx_t* jp, uint64_t value); NONULL d_token_t* json_create_string(json_ctx_t* jp, char* value, int len); NONULL d_token_t* json_create_bytes(json_ctx_t* jp, bytes_t value); -NONULL d_token_t* json_create_object(json_ctx_t* jp); -NONULL d_token_t* json_create_array(json_ctx_t* jp); -NONULL d_token_t* json_object_add_prop(d_token_t* object, d_key_t key, d_token_t* value); -NONULL d_token_t* json_array_add_value(d_token_t* object, d_token_t* value); +NONULL int json_create_object(json_ctx_t* jp); +NONULL int json_create_array(json_ctx_t* jp); +NONULL void json_object_add_prop(json_ctx_t* jp, int ob_index, d_key_t key, d_token_t* value); +NONULL void json_array_add_value(json_ctx_t* jp, int parent_index, d_token_t* value); // Helper function to map string to 2byte keys (only for tests or debugging) char* d_get_keystr(json_ctx_t* json, d_key_t k); /**< returns the string for a key. This only works for index keys or known keys! */ diff --git a/c/include/in3/eth_api.h b/c/include/in3/eth_api.h index f9a70d6e6..aa07000ab 100644 --- a/c/include/in3/eth_api.h +++ b/c/include/in3/eth_api.h @@ -183,6 +183,7 @@ char* eth_wait_for_receipt(in3_t* in3, bytes32_t tx_hash); void eth_log_free(eth_log_t* log); /**< Frees a eth_log_t object */ void eth_tx_receipt_free(eth_tx_receipt_t* txr); /**< Frees a eth_tx_receipt_t object */ int string_val_to_bytes(char* val, char* unit, bytes32_t target); /**< reades the string as hex or decimal and converts it into bytes. the value may also contains a suffix as unit like '1.5eth` which will convert it into wei. the target-pointer must be at least as big as the strlen. The length of the bytes will be returned or a negative value in case of an error.*/ +char* bytes_to_string_val(bytes_t wei, int exp, int digits); /**< converts the bytes value to a decimal string */ in3_ret_t in3_register_eth_api(in3_t* c); /**< this function should only be called once and will register the eth-API verifier.*/ #ifdef __cplusplus } diff --git a/c/include/in3/request.h b/c/include/in3/request.h index 114de40b9..7b97f557a 100644 --- a/c/include/in3/request.h +++ b/c/include/in3/request.h @@ -339,7 +339,7 @@ NONULL void req_free( * ```c in3_ret_t get_from_nodes(in3_req_t* parent, char* method, char* params, bytes_t* dst) { // check if the method is already existing - in3_req_t* req = req_find_required(parent, method); + in3_req_t* req = req_find_required(parent, method, NULL); if (ctx) { // found one - so we check if it is useable. switch (in3_req_state(ctx)) { @@ -386,9 +386,11 @@ NONULL in3_ret_t req_add_required( * * This method is used internaly to find a previously added context. */ -NONULL in3_req_t* req_find_required( - const in3_req_t* parent, /**< [in] the current request context. */ - const char* method /**< [in] the method of the rpc-request. */ +NONULL_FOR((1, 2)) +in3_req_t* req_find_required( + const in3_req_t* parent, /**< [in] the current request context. */ + const char* method, /**< [in] the method of the rpc-request. */ + const char* param_query /**< [in] a optional string within thew params. */ ); /** * removes a required context after usage. diff --git a/c/include/in3/scache.h b/c/include/in3/scache.h index 4f3970b64..6df98fa4b 100644 --- a/c/include/in3/scache.h +++ b/c/include/in3/scache.h @@ -53,6 +53,7 @@ typedef enum cache_props { CACHE_PROP_MUST_FREE = 0x1, /**< indicates the content must be freed*/ CACHE_PROP_SRC_REQ = 0x2, /**< the value holds the src-request */ CACHE_PROP_ONLY_EXTERNAL = 0x4, /**< should only be freed if the context is external */ + CACHE_PROP_JSON = 0x8, /**< indicates the content is a json_ctxt and must be freed as such*/ CACHE_PROP_PAYMENT = 0x80 /**< This cache-entry is a payment.data */ } cache_props_t; /** diff --git a/c/include/in3/stringbuilder.h b/c/include/in3/stringbuilder.h index 8a652de4e..ad75dd236 100644 --- a/c/include/in3/stringbuilder.h +++ b/c/include/in3/stringbuilder.h @@ -82,10 +82,10 @@ NONULL_FOR((1, 3)) sb_t* sb_add_bytes(sb_t* sb, const char* prefix, const bytes_t* bytes, int len, bool as_array); /**< add bytes as 0x-prefixed hexcoded string (including an optional prefix), if len>1 is passed bytes maybe an array ( if as_array==true) */ NONULL sb_t* sb_add_hexuint_l(sb_t* sb, uintmax_t uint, size_t l); /**< add a integer value as hexcoded, 0x-prefixed string*/ NONULL sb_t* sb_add_escaped_chars(sb_t* sb, const char* chars); /**< add chars but escapes all quotes */ -NONULL sb_t* sb_add_int(sb_t* sb, uint64_t val); /**< adds a numeric value to the stringbuilder */ +NONULL sb_t* sb_add_int(sb_t* sb, int64_t val); /**< adds a numeric value to the stringbuilder */ NONULL char* format_json(const char* json); /**< format a json string and returns a new string, which needs to be freed */ NONULL_FOR((1)) -sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, unsigned int fix_size); +sb_t* sb_add_rawbytes(sb_t* sb, char* prefix, bytes_t b, int fix_size); sb_t* sb_print(sb_t* sb, const char* fmt, ...); sb_t* sb_vprint(sb_t* sb, const char* fmt, va_list args); diff --git a/c/include/in3/utils.h b/c/include/in3/utils.h index 64acd9d1c..9f6a71cf8 100644 --- a/c/include/in3/utils.h +++ b/c/include/in3/utils.h @@ -319,6 +319,11 @@ int64_t parse_float_val(const char* data, /**< the data string*/ int32_t expo /**< the exponent */ ); +/** + * simple add function, which adds the bytes (b) to a + */ +void b256_add(bytes32_t a, uint8_t* b, wlen_t len_b); + #ifdef THREADSAFE #define _NAME(x, y) x##y #if defined(_MSC_VER) || defined(__MINGW32__) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 7d63e3153..1368e97d4 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -757,7 +757,7 @@ int main(int argc, char* argv[]) { in3_plugin_register(c, PLGN_ACT_TRANSPORT, debug_transport, NULL, true); -#ifndef USE_WINHTTP +#ifdef USE_WINHTTP rc = "1"; #endif From 5aaf63bd708eef1a49719956c0995d873fa749d7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 21 Mar 2021 09:30:37 +0100 Subject: [PATCH 004/221] fix format --- c/src/verifier/eth1/evm/evm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/verifier/eth1/evm/evm.h b/c/src/verifier/eth1/evm/evm.h index 53322168d..050a79d1b 100644 --- a/c/src/verifier/eth1/evm/evm.h +++ b/c/src/verifier/eth1/evm/evm.h @@ -85,7 +85,7 @@ typedef enum evm_state { #define EVM_PROP_ISTANBUL 32 #define EVM_PROP_NO_FINALIZE 32768 #define EVM_PROP_STATIC 256 -#define EVM_PROP_TXCREATE 512 /**< executing a creation transaction > */ +#define EVM_PROP_TXCREATE 512 /**< executing a creation transaction > */ #define EVM_PROP_CALL_DEPEND_ON_REFUND 1024 /**< executing code that depends on subcall gas refund to succeed > */ #define EVM_ENV_BALANCE 1 From 1d54f2cd1e30537a8b1d9821e2a0a6cc3d864e20 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 21 Mar 2021 09:32:05 +0100 Subject: [PATCH 005/221] fix request count --- c/test/testdata/cmd/eth_blockNumber.txt | 2 +- c/test/testdata/cmd/eth_getBlockByNumber.txt | 2 +- c/test/testdata/cmd/eth_getStorageAt_empty.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/test/testdata/cmd/eth_blockNumber.txt b/c/test/testdata/cmd/eth_blockNumber.txt index 36b20a370..120afbc57 100644 --- a/c/test/testdata/cmd/eth_blockNumber.txt +++ b/c/test/testdata/cmd/eth_blockNumber.txt @@ -1,4 +1,4 @@ -:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_blockNumber.txt eth_blockNumber +:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_blockNumber.txt eth_blockNumber -rc 1 :: time 1607332761 diff --git a/c/test/testdata/cmd/eth_getBlockByNumber.txt b/c/test/testdata/cmd/eth_getBlockByNumber.txt index d504e277a..3dca98c9b 100644 --- a/c/test/testdata/cmd/eth_getBlockByNumber.txt +++ b/c/test/testdata/cmd/eth_getBlockByNumber.txt @@ -1,4 +1,4 @@ -:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_getBlockByNumber.txt eth_getBlockByNumber latest false +:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_getBlockByNumber.txt eth_getBlockByNumber latest false -rc 1 :: time 1607332862 diff --git a/c/test/testdata/cmd/eth_getStorageAt_empty.txt b/c/test/testdata/cmd/eth_getStorageAt_empty.txt index 2ca004a3c..b6af389ab 100644 --- a/c/test/testdata/cmd/eth_getStorageAt_empty.txt +++ b/c/test/testdata/cmd/eth_getStorageAt_empty.txt @@ -1,4 +1,4 @@ -:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_getStorageAt_empty.txt eth_getStorageAt 0xe0060c57527ff36122342daebbeb19e910f3038b 0x0000000000000000000000000000000000000000000000000000000000000000 latest +:: cmd ./bin/in3 -fi ../c/test/testdata/cmd/eth_getStorageAt_empty.txt eth_getStorageAt 0xe0060c57527ff36122342daebbeb19e910f3038b 0x0000000000000000000000000000000000000000000000000000000000000000 latest -rc 1 :: time 1607333024 From 3174515a74916235f787eff80c1f85db6c1e001d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 21 Mar 2021 19:27:36 +0100 Subject: [PATCH 006/221] add binding_checker --- c/src/core/util/debug.h | 2 ++ c/src/verifier/btc/btc.c | 11 ++++--- c/src/verifier/eth1/basic/eth_basic.c | 26 +++++++--------- c/src/verifier/eth1/full/eth_full.c | 3 +- c/src/verifier/eth1/nano/eth_nano.c | 3 +- c/src/verifier/ipfs/ipfs.c | 5 +-- java/src/in3/zksync/API.java | 36 ++++++++++----------- scripts/check_bindings.js | 45 +++++++++++++++++++++++++++ 8 files changed, 90 insertions(+), 41 deletions(-) create mode 100644 scripts/check_bindings.js diff --git a/c/src/core/util/debug.h b/c/src/core/util/debug.h index 72d0b5e09..609e21b3b 100644 --- a/c/src/core/util/debug.h +++ b/c/src/core/util/debug.h @@ -176,4 +176,6 @@ static inline void add_hex(sb_t* sb, char prefix, const char* property, bytes_t /** used for exeuting a function based on the name. This macro will return if the name matches. */ #define TRY_RPC(name, fn) \ if (strcmp(ctx->method, name) == 0) return fn; +/** used in if-conditions and returns true if the vc->method mathes the name. It is also used as marker.*/ +#define VERIFY_RPC(name) (strcmp(vc->method, name) == 0) #endif /* DEBUG_H */ \ No newline at end of file diff --git a/c/src/verifier/btc/btc.c b/c/src/verifier/btc/btc.c index 1871b294e..59020e5fb 100644 --- a/c/src/verifier/btc/btc.c +++ b/c/src/verifier/btc/btc.c @@ -2,6 +2,7 @@ #include "../../core/client/keys.h" #include "../../core/client/plugin.h" #include "../../core/client/request_internal.h" +#include "../../core/util/debug.h" #include "../../core/util/mem.h" #include "../../core/util/utils.h" #include "../../verifier/eth1/nano/eth_nano.h" @@ -444,7 +445,7 @@ static in3_ret_t in3_verify_btc(btc_target_conf_t* conf, in3_vctx_t* vc) { d_token_t* params = d_get(vc->request, K_PARAMS); bytes32_t hash; - if (strcmp(vc->method, "getblock") == 0) { + if (VERIFY_RPC("getblock")) { // mark zksync as experimental REQUIRE_EXPERIMENTAL(vc->req, "btc") @@ -453,22 +454,22 @@ static in3_ret_t in3_verify_btc(btc_target_conf_t* conf, in3_vctx_t* vc) { hex_to_bytes(d_string(block_hash), 64, hash, 32); return btc_verify_block(conf, vc, hash, d_len(params) > 1 ? d_get_int_at(params, 1) : 1, true); } - if (strcmp(vc->method, "getblockcount") == 0) { + if (VERIFY_RPC("getblockcount")) { REQUIRE_EXPERIMENTAL(vc->req, "btc") return btc_verify_blockcount(conf, vc); } - if (strcmp(vc->method, "getblockheader") == 0) { + if (VERIFY_RPC("getblockheader")) { REQUIRE_EXPERIMENTAL(vc->req, "btc") d_token_t* block_hash = d_get_at(params, 0); if (d_len(params) < 1 || d_type(params) != T_ARRAY || d_type(block_hash) != T_STRING || d_len(block_hash) != 64) return vc_err(vc, "Invalid blockhash"); hex_to_bytes(d_string(block_hash), 64, hash, 32); return btc_verify_block(conf, vc, hash, d_len(params) > 1 ? d_get_int_at(params, 1) : 1, false); } - if (strcmp(vc->method, "btc_proofTarget") == 0) { + if (VERIFY_RPC("btc_proofTarget")) { REQUIRE_EXPERIMENTAL(vc->req, "btc") return btc_verify_target_proof(conf, vc, params); } - if (strcmp(vc->method, "getrawtransaction") == 0) { + if (VERIFY_RPC("getrawtransaction")) { REQUIRE_EXPERIMENTAL(vc->req, "btc") d_token_t* tx_id = d_get_at(params, 0); bool json = d_len(params) < 2 ? d_type(vc->result) == T_OBJECT : d_get_int_at(params, 1); diff --git a/c/src/verifier/eth1/basic/eth_basic.c b/c/src/verifier/eth1/basic/eth_basic.c index a83c2a567..9e6f6cf95 100644 --- a/c/src/verifier/eth1/basic/eth_basic.c +++ b/c/src/verifier/eth1/basic/eth_basic.c @@ -60,34 +60,32 @@ in3_ret_t in3_verify_eth_basic(in3_vctx_t* vc) { return IN3_OK; else if (d_type(vc->result) == T_NULL) { // check if there's a proof for non-existence - if (!strcmp(vc->method, "eth_getTransactionByBlockHashAndIndex") || !strcmp(vc->method, "eth_getTransactionByBlockNumberAndIndex")) { + if (VERIFY_RPC("eth_getTransactionByBlockHashAndIndex") || VERIFY_RPC("eth_getTransactionByBlockNumberAndIndex")) return eth_verify_eth_getTransactionByBlock(vc, d_get_at(d_get(vc->request, K_PARAMS), 0), d_get_int_at(d_get(vc->request, K_PARAMS), 1)); - } return IN3_OK; } - if (strcmp(vc->method, "eth_getTransactionByHash") == 0) + if (VERIFY_RPC("eth_getTransactionByHash")) return eth_verify_eth_getTransaction(vc, d_get_bytes_at(d_get(vc->request, K_PARAMS), 0)); - else if (!strcmp(vc->method, "eth_getTransactionByBlockHashAndIndex") || !strcmp(vc->method, "eth_getTransactionByBlockNumberAndIndex")) { + else if (VERIFY_RPC("eth_getTransactionByBlockHashAndIndex") || VERIFY_RPC("eth_getTransactionByBlockNumberAndIndex")) return eth_verify_eth_getTransactionByBlock(vc, d_get_at(d_get(vc->request, K_PARAMS), 0), d_get_int_at(d_get(vc->request, K_PARAMS), 1)); - } - else if (strcmp(vc->method, "eth_getBlockByNumber") == 0) + else if (VERIFY_RPC("eth_getBlockByNumber")) return eth_verify_eth_getBlock(vc, NULL, d_get_long_at(d_get(vc->request, K_PARAMS), 0)); - else if (strcmp(vc->method, "eth_getBlockTransactionCountByHash") == 0) + else if (VERIFY_RPC("eth_getBlockTransactionCountByHash")) return eth_verify_eth_getBlockTransactionCount(vc, d_get_bytes_at(d_get(vc->request, K_PARAMS), 0), 0); - else if (strcmp(vc->method, "eth_getBlockTransactionCountByNumber") == 0) + else if (VERIFY_RPC("eth_getBlockTransactionCountByNumber")) return eth_verify_eth_getBlockTransactionCount(vc, NULL, d_get_long_at(d_get(vc->request, K_PARAMS), 0)); - else if (strcmp(vc->method, "eth_getBlockByHash") == 0) + else if (VERIFY_RPC("eth_getBlockByHash")) return eth_verify_eth_getBlock(vc, d_get_bytes_at(d_get(vc->request, K_PARAMS), 0), 0); - else if (strcmp(vc->method, "eth_getBalance") == 0 || strcmp(vc->method, "eth_getCode") == 0 || strcmp(vc->method, "eth_getStorageAt") == 0 || strcmp(vc->method, "eth_getTransactionCount") == 0) + else if (VERIFY_RPC("eth_getBalance") || VERIFY_RPC("eth_getCode") || VERIFY_RPC("eth_getStorageAt") || VERIFY_RPC("eth_getTransactionCount")) return eth_verify_account_proof(vc); - else if (strcmp(vc->method, "eth_gasPrice") == 0) + else if (VERIFY_RPC("eth_gasPrice")) return IN3_OK; - else if (!strcmp(vc->method, "eth_newFilter") || !strcmp(vc->method, "eth_newBlockFilter") || !strcmp(vc->method, "eth_newPendingFilter") || !strcmp(vc->method, "eth_uninstallFilter") || !strcmp(vc->method, "eth_getFilterChanges")) + else if (VERIFY_RPC("eth_newFilter") || VERIFY_RPC("eth_newBlockFilter") || VERIFY_RPC("eth_newPendingFilter") || VERIFY_RPC("eth_uninstallFilter") || VERIFY_RPC("eth_getFilterChanges")) return IN3_OK; - else if (strcmp(vc->method, "eth_getLogs") == 0) // for txReceipt, we need the txhash + else if (VERIFY_RPC("eth_getLogs")) // for txReceipt, we need the txhash return eth_verify_eth_getLog(vc, d_len(vc->result)); - else if (strcmp(vc->method, "eth_sendRawTransaction") == 0) { + else if (VERIFY_RPC("eth_sendRawTransaction")) { bytes32_t hash; keccak(d_to_bytes(d_get_at(d_get(vc->request, K_PARAMS), 0)), hash); return bytes_cmp(*d_bytes(vc->result), bytes(hash, 32)) ? IN3_OK : vc_err(vc, "the transactionHash of the response does not match the raw transaction!"); diff --git a/c/src/verifier/eth1/full/eth_full.c b/c/src/verifier/eth1/full/eth_full.c index b075ad197..2bfbbecfd 100644 --- a/c/src/verifier/eth1/full/eth_full.c +++ b/c/src/verifier/eth1/full/eth_full.c @@ -36,6 +36,7 @@ #include "../../../core/client/keys.h" #include "../../../core/client/request_internal.h" #include "../../../core/util/data.h" +#include "../../../core/util/debug.h" #include "../../../core/util/log.h" #include "../../../core/util/mem.h" #include "../../../third-party/crypto/ecdsa.h" @@ -55,7 +56,7 @@ in3_ret_t in3_verify_eth_full(void* pdata, in3_plugin_act_t action, void* pctx) // do we have a result? if not it is a vaslid error-response if (!vc->result) return IN3_OK; - if (strcmp(vc->method, "eth_call") == 0) { + if (VERIFY_RPC("eth_call")) { if (eth_verify_account_proof(vc) < 0) return vc_err(vc, "proof could not be validated"); d_token_t* tx = d_get_at(d_get(vc->request, K_PARAMS), 0); bytes_t* address = d_get_byteskl(tx, K_TO, 20); diff --git a/c/src/verifier/eth1/nano/eth_nano.c b/c/src/verifier/eth1/nano/eth_nano.c index a147609e8..b1d297009 100644 --- a/c/src/verifier/eth1/nano/eth_nano.c +++ b/c/src/verifier/eth1/nano/eth_nano.c @@ -36,6 +36,7 @@ #include "../../../core/client/keys.h" #include "../../../core/client/plugin.h" #include "../../../core/client/request.h" +#include "../../../core/util/debug.h" #include "../../../core/util/mem.h" #include "../../../third-party/crypto/ecdsa.h" #include "merkle.h" @@ -61,7 +62,7 @@ in3_ret_t in3_verify_eth_nano(void* p_data, in3_plugin_act_t action, void* pctx) return IN3_OK; } - if (strcmp(vc->method, "eth_getTransactionReceipt") == 0) + if (VERIFY_RPC("eth_getTransactionReceipt")) // for txReceipt, we need the txhash return eth_verify_eth_getTransactionReceipt(vc, d_get_bytes_at(d_get(vc->request, K_PARAMS), 0)); else diff --git a/c/src/verifier/ipfs/ipfs.c b/c/src/verifier/ipfs/ipfs.c index 7c27a7ca4..0f267a2d6 100644 --- a/c/src/verifier/ipfs/ipfs.c +++ b/c/src/verifier/ipfs/ipfs.c @@ -2,6 +2,7 @@ #include "ipfs.h" #include "../../core/client/keys.h" #include "../../core/client/plugin.h" +#include "../../core/util/debug.h" #include "../../core/util/mem.h" #include "../../third-party/crypto/base58.h" #include "../../third-party/crypto/sha2.h" @@ -154,11 +155,11 @@ in3_ret_t in3_verify_ipfs(void* pdata, in3_plugin_act_t action, void* pctx) { if (strcmp(vc->method, "in3_nodeList") == 0) return true; - else if (strcmp(vc->method, "ipfs_get") == 0) + else if (VERIFY_RPC("ipfs_get")) return ipfs_verify_hash(d_string(vc->result), d_get_string_at(params, 1) ? d_get_string_at(params, 1) : "base64", d_get_string_at(params, 0)); - else if (strcmp(vc->method, "ipfs_put") == 0) + else if (VERIFY_RPC("ipfs_put")) return ipfs_verify_hash(d_get_string_at(params, 0), d_get_string_at(params, 1) ? d_get_string_at(params, 1) : "base64", d_string(vc->result)); diff --git a/java/src/in3/zksync/API.java b/java/src/in3/zksync/API.java index efe26137a..f63cae74d 100644 --- a/java/src/in3/zksync/API.java +++ b/java/src/in3/zksync/API.java @@ -20,90 +20,90 @@ public API(IN3 in3) { * the address of the zksync contract. */ public String getContractAddress() { - return (String) in3.sendRPCasObject("zk_contract_address", new Object[] {}); + return (String) in3.sendRPCasObject("zksync_contract_address", new Object[] {}); } /** * the available tokens. */ public Token[] getTokens() { - return Token.asTokens(in3.sendRPCasObject("zk_token", new Object[] {})); + return Token.asTokens(in3.sendRPCasObject("zksync_tokens", new Object[] {})); } /** * returns the current balance, nonce and key for the given account. if address is null, the current configured Account will be used. */ public Account getAccountInfo(String address) { - return Account.asAccount(in3.sendRPCasObject("zk_account_info", address == null ? new Object[] {} : new Object[] {address})); + return Account.asAccount(in3.sendRPCasObject("zksync_account_info", address == null ? new Object[] {} : new Object[] {address})); } /** * the Transaction State. */ public Tx getTransactionInfo(String txid) { - return Tx.asTx(in3.sendRPCasObject("zk_tx_info", new Object[] {txid})); + return Tx.asTx(in3.sendRPCasObject("zksync_tx_info", new Object[] {txid})); } /** * the EthOp State. (State of a deposit or emergencyWithdraw - Transaction ) */ public EthOp getEthOpInfo(String txid) { - return EthOp.asEthOp(in3.sendRPCasObject("zk_ethop_info", new Object[] {txid})); + return EthOp.asEthOp(in3.sendRPCasObject("zksync_ethop_info", new Object[] {txid})); } /** * sets the sync keys and returns the confirmed pubkeyhash */ public String setKey(String token) { - return (String) in3.sendRPCasObject("zk_set_key", new Object[] {token}); + return (String) in3.sendRPCasObject("zksync_set_key", new Object[] {token}); } /** * returns the pubkeyhash based on the current config. */ public String getPubKeyHash() { - return (String) in3.sendRPCasObject("zk_pubkeyhash", new Object[] {}); + return (String) in3.sendRPCasObject("zksync_pubkeyhash", new Object[] {}); } /** * returns the public key based on the current config. */ public String getPubKey() { - return (String) in3.sendRPCasObject("zk_pubkey", new Object[] {}); + return (String) in3.sendRPCasObject("zksync_pubkey", new Object[] {}); } /** * returns the private key based on the current config. */ public String getSyncKey() { - return (String) in3.sendRPCasObject("zk_sync_key", new Object[] {}); + return (String) in3.sendRPCasObject("zksync_sync_key", new Object[] {}); } /** * returns the address of the account based on the current config. */ public String getAccountAddress() { - return (String) in3.sendRPCasObject("zk_account_address", new Object[] {}); + return (String) in3.sendRPCasObject("zksync_account_address", new Object[] {}); } /** * signs the data and returns a musig schnorr signature. */ public String sign(byte[] message) { - return (String) in3.sendRPCasObject("zk_sign", new Object[] {message}); + return (String) in3.sendRPCasObject("zksync_sign", new Object[] {message}); } /** * signs the data and returns a musig schnorr signature. */ public boolean verify(byte[] message, String signature) { - return (Boolean) in3.sendRPCasObject("zk_verify", new Object[] {message, signature}); + return (Boolean) in3.sendRPCasObject("zksync_verify", new Object[] {message, signature}); } /** * calculates the current tx fees for the specified */ public TxFee getTxFee(String txType, String toAddress, String token) { - return TxFee.asTxFee(in3.sendRPCasObject("zk_get_tx_fee", new Object[] {txType, toAddress, token})); + return TxFee.asTxFee(in3.sendRPCasObject("zksync_get_tx_fee", new Object[] {txType, toAddress, token})); } /** @@ -111,7 +111,7 @@ public TxFee getTxFee(String txType, String toAddress, String token) { * returns the ethopId */ public String deposit(BigInteger amount, String token, boolean approveDepositAmountForERC20, String account) { - return (String) in3.sendRPCasObject("zk_deposit", new Object[] {amount, token, approveDepositAmountForERC20, account}); + return (String) in3.sendRPCasObject("zksync_deposit", new Object[] {amount, token, approveDepositAmountForERC20, account}); } /** @@ -119,7 +119,7 @@ public String deposit(BigInteger amount, String token, boolean approveDepositAmo * returns the txid */ public String transfer(String toAddress, BigInteger amount, String token, String fromAccount) { - return (String) in3.sendRPCasObject("zk_transfer", new Object[] {toAddress, amount, token, fromAccount}); + return (String) in3.sendRPCasObject("zksync_transfer", new Object[] {toAddress, amount, token, fromAccount}); } /** @@ -127,7 +127,7 @@ public String transfer(String toAddress, BigInteger amount, String token, String * returns the txid */ public String withdraw(String toAddress, BigInteger amount, String token, String fromAccount) { - return (String) in3.sendRPCasObject("zk_withdraw", new Object[] {toAddress, amount, token, fromAccount}); + return (String) in3.sendRPCasObject("zksync_withdraw", new Object[] {toAddress, amount, token, fromAccount}); } /** @@ -135,7 +135,7 @@ public String withdraw(String toAddress, BigInteger amount, String token, String * returns the txId */ public String emergencyWithdraw(String token) { - return (String) in3.sendRPCasObject("zk_emergency_withdraw", new Object[] {token}); + return (String) in3.sendRPCasObject("zksync_emergency_withdraw", new Object[] {token}); } /** @@ -144,6 +144,6 @@ public String emergencyWithdraw(String token) { public String aggregatePubkey(String[] pubKeys) { StringBuilder s = new StringBuilder(pubKeys[0]); for (int i = 1; i < pubKeys.length; i++) s.append(pubKeys[i].substring(2)); - return (String) in3.sendRPCasObject("zk_aggregate_pubkey", new Object[] {s.toString()}); + return (String) in3.sendRPCasObject("zksync_aggregate_pubkey", new Object[] {s.toString()}); } } diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js new file mode 100644 index 000000000..2b4a32660 --- /dev/null +++ b/scripts/check_bindings.js @@ -0,0 +1,45 @@ +const fs = require('fs') +const { execSync } = require('child_process') + +const exists = (a, name) => a.find(_ => _.name == name) +const grep = (pattern, start) => execSync('grep -r -E ' + pattern + ' --exclude-dir third-party --exclude "debug.h" ' + start).toString().split('\n').filter(_ => _) +const strings = (start, c) => grep(c + '[0-9a-zA-Z_]{4,}' + c, start).map(_ => ((/.*[\"']([0-9a-zA-Z_]{4,})[\"'].*/g).exec(_) || ['', ''])[1]).filter(_ => _) +const getRPCHandlers = () => grep('TRY_RPC', '../c/src').map(line => { + const r = (/(.*?\.c).*TRY_RPC\(\"([^\"]+).*/gm).exec(line) + return { file: r[1], name: r[1].indexOf('zksync') == -1 ? r[2] : 'zksync_' + r[2], type: 'handler' } +}) +const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => { + let r = (/(.*?\.c).*?VERIFY_RPC\(\"([^\"]+)(.*)/gm).exec(line) + const file = r[1] + if (!exists(p, r[2])) p.push({ file, name: r[2], type: 'verifier' }) + while (r = (/(.*?VERIFY_RPC)\(\"([^\"]+)(.*)/gm).exec(r[3])) { + if (!exists(p, r[2])) p.push({ file, name: r[2], type: 'verifier' }) + } + return p +}, []) +const check = val => val ? ' \u2705 ' : ' \u274c ' + +const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()) +const java_rpc = strings('../java/src', '"') +const wasm_rpc = strings('../wasm/src', '\'') +const python_rpc = strings('../python/in3', '"') +const rust_rpc = strings('../rust/in3-rs/src', '"') +const dotnet_rpc = strings('../dotnet/In3', '"', '*.cs') +const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) +all_rpc_names.sort() +console.log('RPC-Method'.padEnd(40) + ' doc java wasm python rust dotnet') +console.log('-'.padEnd(42 + 7 * 6, '-')) + + +all_rpc_names.forEach(rpc => + console.log(rpc.padEnd(40) + ' : ' + + check(doc_rpc.indexOf(rpc) != -1) + + check(java_rpc.indexOf(rpc) != -1) + + check(wasm_rpc.indexOf(rpc) != -1) + + check(python_rpc.indexOf(rpc) != -1) + + check(rust_rpc.indexOf(rpc) != -1) + + check(dotnet_rpc.indexOf(rpc) != -1) + ) +) + + From 86db4b8b371e3ebc46cbead6f5b0cb9d28176636 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 21 Mar 2021 20:47:09 +0100 Subject: [PATCH 007/221] add decryptJSONKey and getBlockCount to wasm --- scripts/check_bindings.js | 27 ++++++++++++++++----------- wasm/src/in3.js | 2 +- wasm/src/in3_util.js | 6 +++--- wasm/src/modules/btc.d.ts | 3 +++ wasm/src/modules/btc.js | 6 ++++++ wasm/src/modules/eth.d.ts | 19 +++++++++++++++++++ wasm/src/modules/eth.js | 22 +++++++++++++++++++--- 7 files changed, 67 insertions(+), 18 deletions(-) mode change 100644 => 100755 scripts/check_bindings.js diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js old mode 100644 new mode 100755 index 2b4a32660..855ba2e5a --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + const fs = require('fs') const { execSync } = require('child_process') @@ -17,29 +19,32 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => } return p }, []) -const check = val => val ? ' \u2705 ' : ' \u274c ' - +const check = (val, c) => val ? ((++res[c]) && ' \u2705 ') : ' \u274c ' +const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0 } const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()) const java_rpc = strings('../java/src', '"') const wasm_rpc = strings('../wasm/src', '\'') const python_rpc = strings('../python/in3', '"') const rust_rpc = strings('../rust/in3-rs/src', '"') const dotnet_rpc = strings('../dotnet/In3', '"', '*.cs') +const c_api = strings('../c/src/api', '"',) const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) all_rpc_names.sort() -console.log('RPC-Method'.padEnd(40) + ' doc java wasm python rust dotnet') -console.log('-'.padEnd(42 + 7 * 6, '-')) +console.log('RPC-Method'.padEnd(40) + ' doc java wasm python rust dotnet c_api') +console.log('-'.padEnd(42 + 7 * 7, '-')) all_rpc_names.forEach(rpc => console.log(rpc.padEnd(40) + ' : ' - + check(doc_rpc.indexOf(rpc) != -1) - + check(java_rpc.indexOf(rpc) != -1) - + check(wasm_rpc.indexOf(rpc) != -1) - + check(python_rpc.indexOf(rpc) != -1) - + check(rust_rpc.indexOf(rpc) != -1) - + check(dotnet_rpc.indexOf(rpc) != -1) + + check(doc_rpc.indexOf(rpc) != -1, 'doc') + + check(java_rpc.indexOf(rpc) != -1, 'java') + + check(wasm_rpc.indexOf(rpc) != -1, 'wasm') + + check(python_rpc.indexOf(rpc) != -1, 'python') + + check(rust_rpc.indexOf(rpc) != -1, 'rust') + + check(dotnet_rpc.indexOf(rpc) != -1, 'dotnet') + + check(c_api.indexOf(rpc) != -1, 'c') ) ) - +console.log("\nSummary:") +Object.keys(res).forEach(k => console.log(k.padEnd(8) + ': ' + (res[k] * 100 / all_rpc_names.length).toFixed(0) + ' % ')) diff --git a/wasm/src/in3.js b/wasm/src/in3.js index e43bd4785..9acb1d5ff 100644 --- a/wasm/src/in3.js +++ b/wasm/src/in3.js @@ -215,7 +215,7 @@ class IN3 { this.transport = this.config.transport delete this.config.transport } - const r = in3w.ccall('in3_config', 'number', ['number', 'string'], [this.ptr, JSON.stringify(this.config)]); + const r = in3w.ccall('in3_config', 'number', ['number', 'string'], [this.ptr, JSON.stringify(this.config)]); // shortcut for 'in3_config' if (r) { const ex = new Error(UTF8ToString(r)) _free(r) diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 3ddf7f1d6..00d493b0f 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -157,7 +157,7 @@ function keccak(val) { function toChecksumAddress(val, chainId = 0) { if (!val) return val - return call_string('to_checksum_address', toUint8Array(val, 20), chainId); + return call_string('to_checksum_address', toUint8Array(val, 20), chainId); // shortcut for 'in3_checksumAddress' } function private2address(pk) { @@ -177,7 +177,7 @@ function abiEncode(sig, ...params) { ? convert(Object.values(a)) : toHex(a) try { - return call_string('wasm_abi_encode', sig, JSON.stringify(convert(params))) + return call_string('wasm_abi_encode', sig, JSON.stringify(convert(params))) // shortcut for 'in3_abiDecode'-method } catch (x) { throw new Error("Error trying to abi encode '" + sig + '": ' + x.message + ' with ' + JSON.stringify(params)) @@ -200,7 +200,7 @@ function abiDecode(sig, data) { else return [] } try { - let res = JSON.parse(call_string('wasm_abi_decode', sig, data, data.byteLength)) + let res = JSON.parse(call_string('wasm_abi_decode', sig, data, data.byteLength)) // shortcut for 'in3_abiEncode'-method return allowOne ? convertType(res, types[0]) : convertTypes(types, res) } catch (x) { throw new Error('Error decoding ' + sig + ' with ' + toHex(data) + ' : ' + x.message) diff --git a/wasm/src/modules/btc.d.ts b/wasm/src/modules/btc.d.ts index 03a116e5a..d97b977ce 100644 --- a/wasm/src/modules/btc.d.ts +++ b/wasm/src/modules/btc.d.ts @@ -203,6 +203,9 @@ export declare interface BtcAPI { /** retrieves the serialized block (bytes) including all transactions */ getBlockBytes(blockHash: Hash): Promise + + /** Returns the number of blocks in the longest blockchain. */ + getBlockCount(): Promise } /** diff --git a/wasm/src/modules/btc.js b/wasm/src/modules/btc.js index 15d9cae16..fd0ed7056 100644 --- a/wasm/src/modules/btc.js +++ b/wasm/src/modules/btc.js @@ -77,6 +77,12 @@ class BtcAPI { } + getBlockCount() { + return this.client.sendRPC('getblockcount', []) + .then(response => response || Promise.reject(new Error(response.error))) + } + + } diff --git a/wasm/src/modules/eth.d.ts b/wasm/src/modules/eth.d.ts index 568bc549d..36258978a 100644 --- a/wasm/src/modules/eth.d.ts +++ b/wasm/src/modules/eth.d.ts @@ -259,6 +259,19 @@ export interface AccountAPI { */ add(pk: string | BufferType): Promise + /** + * decrypts a JSON Keystore file as defined in the Web3 Secret Storage Definition . The result is the raw private key. + * @param keystore the keystore data + * @param passphrase the passphrase + */ + decryptKeystore(keystore: any, passphrase: string): Promise + + /** + * adds a key from a JSON Keystore file as defined in the Web3 Secret Storage Definition . This method returns address of the pk. + * @param keystore the keystore data + * @param passphrase the passphrase + */ + addKeyStore(keystore: any, passphrase: string): Promise } @@ -462,6 +475,12 @@ export interface EthAPI { * Returns the number of uncles in a block from a block matching the given block hash. */ getUncleCountByBlockNumber(block: BlockType): Promise; + + /** + * adds a filter for pending transaction (only available for local rpc) + */ + newPendingFilter(): Promise; + /** * Creates a filter in the node, to notify when a new block arrives. To check if the state has changed, call eth_getFilterChanges. */ diff --git a/wasm/src/modules/eth.js b/wasm/src/modules/eth.js index 2bccbe03a..e41a5c0b2 100644 --- a/wasm/src/modules/eth.js +++ b/wasm/src/modules/eth.js @@ -38,6 +38,16 @@ class AccountAPI { add(pk) { return this.client.sendRPC("in3_addRawKey", [toHex(pk)]).then(toChecksumAddress) } + + + decryptKeystore(keystore, passphrase) { + return this.client.sendRPC('in3_decryptKey', [keystore, passphrase]).then(toBuffer) + } + + addKeyStore(keystore, passphrase) { + return this.client.sendRPC('in3_decryptKey', [keystore, passphrase]).then(pk => this.add(pk)) + } + } class EthAPI { @@ -308,6 +318,14 @@ class EthAPI { return this.send('eth_newFilter', filter) } + /** + * adds a filter for pending transaction (only available for local rpc) + * @returns + */ + newPendingFilter() { + return this.send('eth_newPendingFilter') + } + /** * Creates a filter in the node, to notify when new pending transactions arrive. * @@ -343,8 +361,6 @@ class EthAPI { return this.send('eth_accounts') } - - /** * Creates new message call transaction or a contract creation for signed transactions. */ @@ -388,7 +404,7 @@ class EthAPI { const txHash = await this.send('eth_sendTransaction', tx) - if (args.confirmations === undefined) args.confirmations = 1 + if (args.confirmations === undefined) args.confirmations = 1 // same as 'eth_sendTransactionAndWait' // send it return args.confirmations ? confirm(txHash, this, parseInt(tx.gas || 21000), args.confirmations, args.timeout || 60) : txHash From f725f7ac0c3e632fd6418f9696eaca3f8aa73b52 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 07:19:09 +0100 Subject: [PATCH 008/221] fix keccak for wasm --- wasm/src/in3_util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 00d493b0f..9bd715b6b 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -152,7 +152,7 @@ function toBigInt(val) { function keccak(val) { if (!val) return val val = toUint8Array(val) - return toBuffer(call_buffer('hash_keccak', 32, val, val.byteLength)) + return toBuffer(call_buffer('hash_keccak', 32, val, val.byteLength)) // shortcut for 'web3_sha3' or 'keccak' } function toChecksumAddress(val, chainId = 0) { From 51f951c6e5416f1a72e2f639abaddc0be2526003 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 13:17:34 +0100 Subject: [PATCH 009/221] add params-check --- c/src/api/eth1/rpc_api.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 24dacbc80..42d684ec0 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -516,6 +516,8 @@ static in3_ret_t in3_decryptKey(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1); + CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_OBJECT); d_token_t* tx = d_get_at(ctx->params, 0); bytes_t dst = {0}; #if defined(ETH_BASIC) || defined(ETH_FULL) @@ -538,7 +540,7 @@ static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { #if defined(ETH_BASIC) || defined(ETH_FULL) TRY(eth_sign_raw_tx(*data, ctx->req, from, &dst)) #else - if (data || ctx || from[0] || ctx->params) return req_set_error(ctx->req, "eth_basic is needed in order to use eth_prepareTx", IN3_EINVAL); + if (data || ctx || from[0] || ctx->params) return req_set_error(ctx->req, "eth_basic is needed in order to use eth_signTx", IN3_EINVAL); #endif in3_rpc_handle_with_bytes(ctx, dst); _free(dst.data); From f8ba43b0bba053ae3f2e2472ff894e77e412c281 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 13:17:44 +0100 Subject: [PATCH 010/221] add sha256 --- wasm/src/wasm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/wasm/src/wasm.c b/wasm/src/wasm.c index ce679ce17..7ac26281d 100644 --- a/wasm/src/wasm.c +++ b/wasm/src/wasm.c @@ -41,6 +41,7 @@ #include "../../c/src/nodeselect/full/nodelist.h" #include "../../c/src/third-party/crypto/ecdsa.h" #include "../../c/src/third-party/crypto/secp256k1.h" +#include "../../c/src/third-party/crypto/sha2.h" #ifdef ETH_FULL #include "../../c/src/third-party/tommath/tommath.h" #endif @@ -394,6 +395,20 @@ uint8_t* EMSCRIPTEN_KEEPALIVE hash_keccak(uint8_t* data, int len) { return result; } +uint8_t* EMSCRIPTEN_KEEPALIVE hash_sha256(uint8_t* data, int len) { + uint8_t* result = malloc(32); + if (result) { + SHA256_CTX c; + sha256_Init(&c); + sha256_Update(&c, data, len); + sha256_Final(&c, result); + } + else + in3_set_error("malloc failed"); + + return result; +} + char* EMSCRIPTEN_KEEPALIVE to_checksum_address(address_t adr, int chain_id) { char* result = malloc(43); if (!result) return err_string("malloc failed"); @@ -496,6 +511,15 @@ uint8_t* EMSCRIPTEN_KEEPALIVE private_to_address(bytes32_t prv_key) { return dst; } +/** private key to address */ +uint8_t* EMSCRIPTEN_KEEPALIVE private_to_public(bytes32_t prv_key) { + uint8_t* dst = malloc(64); + uint8_t public_key[65], sdata[32]; + ecdsa_get_public_key65(&secp256k1, prv_key, public_key); + memcpy(dst, public_key + 1, 64); + return dst; +} + /** signs the given data */ uint8_t* EMSCRIPTEN_KEEPALIVE ec_sign(bytes32_t pk, d_signature_type_t type, uint8_t* data, int len, bool adjust_v) { uint8_t* dst = malloc(65); From 86fe3fb437a2f2eb7fca45dbe02bdc6533b7287d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 13:17:59 +0100 Subject: [PATCH 011/221] add missing rpc-functions --- wasm/src/in3.js | 18 +++++++++++++- wasm/src/in3_util.js | 20 ++++++++++++--- wasm/src/index.d.ts | 12 +++++++++ wasm/src/modules/eth.d.ts | 51 ++++++++++++++++++++++++++++++++++----- wasm/src/modules/eth.js | 31 +++++++++++++++++++++--- wasm/test/testEthApi.js | 6 +++++ 6 files changed, 124 insertions(+), 14 deletions(-) diff --git a/wasm/src/in3.js b/wasm/src/in3.js index 9acb1d5ff..098bef896 100644 --- a/wasm/src/in3.js +++ b/wasm/src/in3.js @@ -47,7 +47,8 @@ if (isBrowserEnvironment) { // for browsers in3w.in3_cache = { get: key => window.localStorage.getItem('in3.' + key), - set: (key, value) => window.localStorage.setItem('in3.' + key, value) + set: (key, value) => window.localStorage.setItem('in3.' + key, value), + clear: () => window.localStorage.clear() } in3w.transport = (url, payload, timeout, method, headers) => Promise.race([ fetch(url, { @@ -75,6 +76,12 @@ else { }, set(key, value) { fs.writeFileSync('.in3/' + key, Buffer.from(value, 'hex')) + }, + clear() { + try { + fs.rmdirSync('.in3', { recursive: true }) + fs.mkdirSync('.in3') + } catch (x) { } } } @@ -224,6 +231,10 @@ class IN3 { } } + getConfig() { + return this.execLocal('in3_getConfig', []) + } + /** * sends one or a multiple requests. * if the request is a array the response will be a array as well. @@ -484,6 +495,11 @@ IN3.setStorage = function (fn) { in3w.in3_cache = fn } +// deletes the cache +IN3.clearStorage = function () { // same as 'in3_cacheClear' + if (in3w.in3_cache.clear) in3w.in3_cache.clear() +} + IN3.freeAll = function () { Object.keys(clients).forEach(_ => clients[_].free()) } diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 9bd715b6b..e6a13482c 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -149,10 +149,16 @@ function toBigInt(val) { return BigInt(toHex(val)) } -function keccak(val) { +function keccak(val) { // shortcut for the 'keccak' rpc-call if (!val) return val val = toUint8Array(val) - return toBuffer(call_buffer('hash_keccak', 32, val, val.byteLength)) // shortcut for 'web3_sha3' or 'keccak' + return toBuffer(call_buffer('hash_keccak', 32, val, val.byteLength)) // keccak is also a alias for 'web3_sha3' +} + +function sha256(val) { + if (!val) return val + val = toUint8Array(val) + return toBuffer(call_buffer('hash_sha256', 32, val, val.byteLength)) // shortcut for 'sha256' } function toChecksumAddress(val, chainId = 0) { @@ -163,7 +169,13 @@ function toChecksumAddress(val, chainId = 0) { function private2address(pk) { if (!pk) return pk pk = toUint8Array(pk) - return toChecksumAddress(call_buffer('private_to_address', 20, pk, pk.byteLength)) + return toChecksumAddress(call_buffer('private_to_address', 20, pk, pk.byteLength)) // alias for 'in3_pk2address' +} + +function private2public(pk) { + if (!pk) return pk + pk = toUint8Array(pk) + return toChecksumAddress(call_buffer('private_to_public', 20, pk, pk.byteLength)) // alias for 'in3_pk2public' } function checkAddressChecksum(ad, chain = 0) { @@ -573,12 +585,14 @@ const util = { padStart, padEnd, keccak, + sha256, toChecksumAddress, abiEncode, abiDecode, ecSign, splitSignature, private2address, + private2public, soliditySha3, randomBytes, createSignatureHash, diff --git a/wasm/src/index.d.ts b/wasm/src/index.d.ts index 2fb960da1..62c20b4d4 100644 --- a/wasm/src/index.d.ts +++ b/wasm/src/index.d.ts @@ -755,6 +755,12 @@ export declare interface Utils { */ keccak(data: BufferType | Data): BufferType + /** + * calculates the sha256 hash for the given data. + * @param data the data as Uint8Array or hex data. + */ + sha256(data: BufferType | Data): BufferType + /** * returns a Buffer with strong random bytes. * Thsi will use the browsers crypto-module or in case of nodejs use the crypto-module there. @@ -820,4 +826,10 @@ export declare interface Utils { * @param pk the private key. */ private2address(pk: Hex | BufferType): Address + + /** + * generates the public address (64 bytes) from the private key + * @param pk the raw private key + */ + private2public(pk: Hex | BufferType): BufferType } diff --git a/wasm/src/modules/eth.d.ts b/wasm/src/modules/eth.d.ts index 36258978a..cd9431849 100644 --- a/wasm/src/modules/eth.d.ts +++ b/wasm/src/modules/eth.d.ts @@ -257,21 +257,56 @@ export interface AccountAPI { * This method returns address of the pk * @param pk */ - add(pk: string | BufferType): Promise + add(pk: string | BufferType): string /** * decrypts a JSON Keystore file as defined in the Web3 Secret Storage Definition . The result is the raw private key. * @param keystore the keystore data * @param passphrase the passphrase */ - decryptKeystore(keystore: any, passphrase: string): Promise + decryptKeystore(keystore: any, passphrase: string): BufferType /** * adds a key from a JSON Keystore file as defined in the Web3 Secret Storage Definition . This method returns address of the pk. * @param keystore the keystore data * @param passphrase the passphrase */ - addKeyStore(keystore: any, passphrase: string): Promise + addKeyStore(keystore: any, passphrase: string): String + + /** + * recovers a ecdsa signature. + * @param msg the message + * @param sig the signature (must be 65bytes in hex or Buffer) + * @param msgtype the type (raw : the message must be hashed first (default), 'hash' the message is already a 32byte hash, 'eth_sign' - the message will be hashed with EthereumSignedMessage-Prefix) + */ + ecrecover(msg: string | BufferType, sig: string | BufferType, msgtype?: 'eth_sign' | 'raw' | 'hash'): { + address: string, + publicKey: string + } + + /** + * creates a signature with a previously registered signer based on the data + * @param msg the message to sign + * @param account the address of the account ( if null, the first available account is used ). If the account is a 32byte hex or buffer, it it will be used as raw private key. + * @param msgtype the type (raw : the message must be hashed first (default), 'hash' the message is already a 32byte hash, 'eth_sign' - the message will be hashed with EthereumSignedMessage-Prefix) + */ + signData(msg: string | BufferType, account: string | BufferType, msgtype?: 'eth_sign' | 'raw' | 'hash'): Promise + + + /** + * creates a signature with a previously registered signer based on the data + * @param msg the message to sign + * @param account the address of the account ( if null, the first available account is used ). If the account is a 32byte hex or buffer, it it will be used as raw private key. + * @param msgtype the type (raw : the message must be hashed first (default), 'hash' the message is already a 32byte hash, 'eth_sign' - the message will be hashed with EthereumSignedMessage-Prefix) + */ + signRawTx(msg: string | BufferType, account: string | BufferType, msgtype?: 'eth_sign' | 'raw' | 'hash'): Promise + + /** + * prepares a Transaction by creating a unsigned raw transaction. + * @param tx the tx parameter + */ + prepareTx(tx: TxRequest): Promise + } @@ -515,10 +550,14 @@ export interface EthAPI { /** * Returns the value in wei as hexstring. */ - toWei(value: string, unit: string): string; + toWei(value: string, unit?: string): string; + /** + * Returns a formated String in the specified unit (or eth if not specified). If digits are specified, the number of digits behind the comma can be limited. + */ + fromWei(value: string, unit?: string, digits?: number): string; /** - * Returns the state of the underlying node. - */ + * Returns the state of the underlying node. + */ syncing(): Promise this.add(pk)) + return this.add(this.client.sendRPC('in3_decryptKey', [keystore, passphrase])) + } + + ecrecover(msg, sig, sigtype) { + return this.client.execLocal('in3_ecrecover', [toHex(msg), toHex(sig), sigtype || 'raw']) + } + + signData(msg, account, msgtype) { + return this.client.sendRPC('in3_signData', [toHex(msg), toHex(account), msgtype || 'raw']) + } + + signRawTx(rawTx, account) { + return this.client.sendRPC('in3_signTx', [toHex(rawTx), toHex(account)]).then(toBuffer) + } + + prepareTx(tx) { + return this.client.sendRPC('in3_prepareTx', [tx]).then(toBuffer) } } @@ -77,12 +93,19 @@ class EthAPI { } /** - * Returns the number of most recent block. () + * converts the tokens into wei */ toWei(val, unit = 'eth') { return this.client.execLocal('in3_toWei', [val, unit]) } + /** + * converts the Wei in a formatted token string. + */ + fromWei(val, unit = 'eth', digits = -1) { + return this.client.execLocal('in3_fromWei', digits == -1 ? [toHex(val), unit] : [toHex(val), unit, digits]) + } + /** * Returns the current price per g wei. () */ diff --git a/wasm/test/testEthApi.js b/wasm/test/testEthApi.js index 190cedf64..7a5f188ba 100644 --- a/wasm/test/testEthApi.js +++ b/wasm/test/testEthApi.js @@ -470,6 +470,12 @@ describe('EthAPI-Tests', () => { assert.equal(val, "0x01159183c4793db800") }) + it('eth.fromWei()', async () => { + let client = createClient() + const val = client.eth.fromWei('1450000000000000000', 'eth') + assert.equal(val, "1.45") + }) + it('eth.newFilter()', async () => { mockResponse('eth_blockNumber', '0x8e4daa') let client = createClient() From 1427362b245f0d24f0b75bd107851d9822986a6d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 13:18:18 +0100 Subject: [PATCH 012/221] special handling for btc_targetProof --- scripts/check_bindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 855ba2e5a..8f03301d6 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -21,7 +21,7 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => }, []) const check = (val, c) => val ? ((++res[c]) && ' \u2705 ') : ' \u274c ' const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0 } -const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()) +const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()).map(_ => _ === 'proofTarget' ? 'btc_proofTarget' : _) const java_rpc = strings('../java/src', '"') const wasm_rpc = strings('../wasm/src', '\'') const python_rpc = strings('../python/in3', '"') From fc4062a7be2b549c377de41798e1da7503b5f30e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 22 Mar 2021 14:54:36 +0100 Subject: [PATCH 013/221] remove prrofTarget from external call --- c/src/verifier/btc/btc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/verifier/btc/btc.c b/c/src/verifier/btc/btc.c index 59020e5fb..3c5577c27 100644 --- a/c/src/verifier/btc/btc.c +++ b/c/src/verifier/btc/btc.c @@ -465,7 +465,7 @@ static in3_ret_t in3_verify_btc(btc_target_conf_t* conf, in3_vctx_t* vc) { hex_to_bytes(d_string(block_hash), 64, hash, 32); return btc_verify_block(conf, vc, hash, d_len(params) > 1 ? d_get_int_at(params, 1) : 1, false); } - if (VERIFY_RPC("btc_proofTarget")) { + if (strcmp(vc->method, "btc_proofTarget") == 0) { // we use strcmp directly here, because btc_proofTarget is an internal rpc-call, which does not have to be part of any API. REQUIRE_EXPERIMENTAL(vc->req, "btc") return btc_verify_target_proof(conf, vc, params); } From 757a3547dd8ecf06d49bb10409e805ba92714f70 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:12:50 +0100 Subject: [PATCH 014/221] add script to build docu --- scripts/build_rpc_docu.js | 111 ++++++++++++++++++++++++++++++++++++++ scripts/check_bindings.js | 10 ++-- wasm/test/package.json | 5 +- 3 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 scripts/build_rpc_docu.js diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js new file mode 100644 index 000000000..00958721e --- /dev/null +++ b/scripts/build_rpc_docu.js @@ -0,0 +1,111 @@ +const yaml = require('../wasm/test/node_modules/yaml') +const fs = require('fs') + +const docs = {} +let config = {} +function scan(dir) { + for (const f of fs.readdirSync(dir, { withFileTypes: true })) { + if (f.name == 'rpc.yml') { + const ob = yaml.parse(fs.readFileSync(dir + '/' + f.name, 'utf-8')) + for (const k of Object.keys(ob)) { + if (ob[k].config) config = { ...config, ...ob[k].config } + delete ob[k].config + docs[k] = { ...docs[k], ...ob[k] } + } + } + else if (f.isDirectory()) scan(dir + '/' + f.name) + } +} +function print_object(def, pad) { + for (const prop of Object.keys(def)) { + let s = pad + '* **' + prop + '**' + const p = def[prop] + if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' + if (p.optional) s += ' *(optional)*' + if (p.descr) s += ' - ' + p.descr + if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' + console.log(s) + if (typeof p.type === 'object') { + console.log('The ' + prop + ' object supports the following properties :\n' + pad) + print_object(p.type, pad + ' ') + } + + if (p.example) console.log('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) + console.log(pad + '\n') + } + +} +scan('../c/src') +docs.in3.in3_config.params.config.type = config +console.log('# API RPC\n\n') +console.log('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') + +for (const s of Object.keys(docs).sort()) { + const rpcs = docs[s] + console.log("## " + s + "\n\n") + if (rpcs.descr) console.log(rpcs.descr + '\n') + delete rpcs.descr + for (const rpc of Object.keys(rpcs).sort()) { + console.log('### ' + rpc + '\n\n') + const def = rpcs[rpc] + if (def.descr) console.log(def.descr + '\n') + if (def.params) { + console.log("Parameters:\n") + let i = 1 + for (const par of Object.keys(def.params)) { + const p = def.params[par] + let s = (i++) + '. `' + par + '`' + if (p.type) s += ':' + (typeof p.type === 'string' ? p.type : 'object') + if (p.descr) s += ' - ' + p.descr + console.log(s) + if (typeof p.type === 'object') { + console.log('\nThe ' + par + ' params support the following properties :\n') + print_object(p.type, '') + } + + } + console.log() + } + else + console.log("Parameters: - \n") + + if (def.returns) { + if (def.returns.type) { + console.log('Returns: ' + (typeof def.returns.type === 'string' ? def.returns.type : 'object') + '\n\n' + def.returns.descr + '\n') + if (typeof def.returns.type === 'object') { + console.log('\nThe return value contains the following properties :\n') + print_object(def.returns.type, '') + } + } + else + console.log('Returns:\n\n' + def.returns.descr + '\n') + } + + if (def.proof) { + console.log('Proof:\n\n' + def.proof.descr + '\n') + if (def.proof.type) { + console.log("This proof section contains the following properties:\n\n") + print_object(def.proof.type, '') + console.log("\n\n") + } + } + + + + if (def.example && def.example.request) { + console.log('Request:\n') + console.log('```js\n' + JSON.stringify({ method: rpc, params: def.example.request }, null, 2)) + console.log('```\n') + } + if (def.example && def.example.response) { + const data = { result: def.example.response } + if (def.example.in3) data.in3 = def.example.in3 + console.log('Response:\n') + console.log('```js\n' + JSON.stringify(data, null, 2)) + console.log('```\n') + } + + } +} + + diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 8f03301d6..10c000d0b 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -20,7 +20,7 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => return p }, []) const check = (val, c) => val ? ((++res[c]) && ' \u2705 ') : ' \u274c ' -const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0 } +const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0, autocompl: 0 } const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()).map(_ => _ === 'proofTarget' ? 'btc_proofTarget' : _) const java_rpc = strings('../java/src', '"') const wasm_rpc = strings('../wasm/src', '\'') @@ -28,21 +28,23 @@ const python_rpc = strings('../python/in3', '"') const rust_rpc = strings('../rust/in3-rs/src', '"') const dotnet_rpc = strings('../dotnet/In3', '"', '*.cs') const c_api = strings('../c/src/api', '"',) +const autocomplete = grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]) const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) all_rpc_names.sort() -console.log('RPC-Method'.padEnd(40) + ' doc java wasm python rust dotnet c_api') -console.log('-'.padEnd(42 + 7 * 7, '-')) +console.log('RPC-Method'.padEnd(40) + ' doc wasm java python rust dotnet c_api autocmpl') +console.log('-'.padEnd(44 + 7 * 8, '-')) all_rpc_names.forEach(rpc => console.log(rpc.padEnd(40) + ' : ' + check(doc_rpc.indexOf(rpc) != -1, 'doc') - + check(java_rpc.indexOf(rpc) != -1, 'java') + check(wasm_rpc.indexOf(rpc) != -1, 'wasm') + + check(java_rpc.indexOf(rpc) != -1, 'java') + check(python_rpc.indexOf(rpc) != -1, 'python') + check(rust_rpc.indexOf(rpc) != -1, 'rust') + check(dotnet_rpc.indexOf(rpc) != -1, 'dotnet') + check(c_api.indexOf(rpc) != -1, 'c') + + check(autocomplete.indexOf(rpc) != -1, 'autocompl') ) ) console.log("\nSummary:") diff --git a/wasm/test/package.json b/wasm/test/package.json index a7c7edaec..780218146 100644 --- a/wasm/test/package.json +++ b/wasm/test/package.json @@ -54,7 +54,8 @@ "eth-lib": "^0.2.8", "in3-common": "^2.0.3-RC1", "ts-node": "^8.10.2", - "typescript": "^3.9.5" + "typescript": "^3.9.5", + "yaml": "^1.10.2" }, "keywords": [ "ethereum", @@ -64,4 +65,4 @@ "client", "jsonrpc" ] -} \ No newline at end of file +} From d9bfa1aaae31c1e752960315a470efe490bec485 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:13:03 +0100 Subject: [PATCH 015/221] organize signer-rpcs --- c/src/signer/pk-signer/signer.c | 60 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index e02383b6b..55f132276 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -36,6 +36,7 @@ #include "../../core/client/keys.h" #include "../../core/client/plugin.h" #include "../../core/client/request_internal.h" +#include "../../core/util/debug.h" #include "../../core/util/mem.h" #include "../../core/util/utils.h" #include "../../third-party/crypto/ecdsa.h" @@ -132,6 +133,35 @@ in3_ret_t eth_set_pk_signer(in3_t* in3, bytes32_t pk) { return in3_plugin_register(in3, PLGN_ACT_SIGN_ACCOUNT | PLGN_ACT_SIGN | PLGN_ACT_TERM, eth_sign_pk, k, false); } +static in3_ret_t add_raw_key(in3_rpc_handle_ctx_t* ctx) { + if (d_len(ctx->params) != 1 || d_type(ctx->params + 1) != T_BYTES || d_len(ctx->params + 1) != 32) + return req_set_error(ctx->req, "one argument with 32 bytes is required!", IN3_EINVAL); + address_t adr; + get_address(d_bytes(ctx->params + 1)->data, adr); + add_key(ctx->req->client, d_bytes(ctx->params + 1)->data); + return in3_rpc_handle_with_bytes(ctx, bytes(adr, 20)); +} + +static in3_ret_t eth_accounts(in3_rpc_handle_ctx_t* ctx) { + sb_t* sb = in3_rpc_handle_start(ctx); + bool first = true; + in3_sign_account_ctx_t sc = {.req = ctx->req, .accounts = NULL, .accounts_len = 0, .signer_type = 0}; + for (in3_plugin_t* p = ctx->req->client->plugins; p; p = p->next) { + if (p->acts & PLGN_ACT_SIGN_ACCOUNT && p->action_fn(p->data, PLGN_ACT_SIGN_ACCOUNT, &sc) == IN3_OK) { + for (int i = 0; i < sc.accounts_len; i++) { + sb_add_rawbytes(sb, first ? "[\"0x" : "\",\"0x", bytes(sc.accounts + i * 20, 20), 20); + first = false; + } + if (sc.accounts) { + _free(sc.accounts); + sc.accounts_len = 0; + } + } + } + sb_add_chars(sb, first ? "[]" : "\"]"); + return in3_rpc_handle_finish(ctx); +} + // RPC-Handler static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { UNUSED_VAR(data); @@ -174,34 +204,8 @@ static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { } case PLGN_ACT_RPC_HANDLE: { - in3_rpc_handle_ctx_t* ctx = action_ctx; - if (strcmp(ctx->method, "in3_addRawKey") == 0) { - if (d_len(ctx->params) != 1 || d_type(ctx->params + 1) != T_BYTES || d_len(ctx->params + 1) != 32) - return req_set_error(ctx->req, "one argument with 32 bytes is required!", IN3_EINVAL); - address_t adr; - get_address(d_bytes(ctx->params + 1)->data, adr); - add_key(ctx->req->client, d_bytes(ctx->params + 1)->data); - return in3_rpc_handle_with_bytes(ctx, bytes(adr, 20)); - } - if (strcmp(ctx->method, "eth_accounts") == 0) { - sb_t* sb = in3_rpc_handle_start(ctx); - bool first = true; - in3_sign_account_ctx_t sc = {.req = ctx->req, .accounts = NULL, .accounts_len = 0, .signer_type = 0}; - for (in3_plugin_t* p = ctx->req->client->plugins; p; p = p->next) { - if (p->acts & PLGN_ACT_SIGN_ACCOUNT && p->action_fn(p->data, PLGN_ACT_SIGN_ACCOUNT, &sc) == IN3_OK) { - for (int i = 0; i < sc.accounts_len; i++) { - sb_add_rawbytes(sb, first ? "[\"0x" : "\",\"0x", bytes(sc.accounts + i * 20, 20), 20); - first = false; - } - if (sc.accounts) { - _free(sc.accounts); - sc.accounts_len = 0; - } - } - } - sb_add_chars(sb, first ? "[]" : "\"]"); - return in3_rpc_handle_finish(ctx); - } + TRY_RPC("in3_addRawKey", add_raw_key(action_ctx)) + TRY_RPC("eth_accounts", eth_accounts(action_ctx)) return IN3_EIGNORE; } From 207851a922d8f2a6b1bf3b74f8bb65256376d264 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:13:20 +0100 Subject: [PATCH 016/221] optimze apis --- c/src/api/eth1/eth_api.c | 3 ++- c/src/api/eth1/rpc_api.c | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/c/src/api/eth1/eth_api.c b/c/src/api/eth1/eth_api.c index 5871af769..576458e4c 100644 --- a/c/src/api/eth1/eth_api.c +++ b/c/src/api/eth1/eth_api.c @@ -464,7 +464,8 @@ in3_ret_t eth_newPendingTransactionFilter(in3_t* in3) { bool eth_uninstallFilter(in3_t* in3, size_t id) { return filter_remove(eth_basic_get_filters(in3), id); } - +// same as "eth_getFilterChanges" +// or "eth_getFilterLogs" in3_ret_t eth_getFilterChanges(in3_t* in3, size_t id, bytes32_t** block_hashes, eth_log_t** logs) { in3_filter_handler_t* filters = eth_basic_get_filters(in3); if (filters == NULL) return IN3_EFIND; diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 42d684ec0..3d1771d04 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -552,14 +552,16 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi UNUSED_VAR(action); in3_rpc_handle_ctx_t* ctx = plugin_ctx; + TRY_RPC("web3_sha3", in3_sha3(ctx)) + TRY_RPC("keccak", in3_sha3(ctx)) + TRY_RPC("sha256", in3_sha256(ctx)) + + if (strncmp(ctx->method, "in3_", 4)) return IN3_EIGNORE; // shortcut TRY_RPC("in3_abiEncode", in3_abiEncode(ctx)) TRY_RPC("in3_abiDecode", in3_abiDecode(ctx)) TRY_RPC("in3_checksumAddress", in3_checkSumAddress(ctx)) TRY_RPC("in3_ens", in3_ens(ctx)) - TRY_RPC("web3_sha3", in3_sha3(ctx)) - TRY_RPC("keccak", in3_sha3(ctx)) - TRY_RPC("sha256", in3_sha256(ctx)) TRY_RPC("in3_toWei", in3_toWei(ctx)) TRY_RPC("in3_fromWei", in3_fromWei(ctx)) TRY_RPC("in3_config", in3_config(ctx)) From 3dca34069f4936039276351dda37206565c5654e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:13:32 +0100 Subject: [PATCH 017/221] define rpc.yml --- c/src/api/eth1/rpc.yml | 544 ++++++++++++++++++++++++++++++ c/src/core/client/rpc.yml | 106 ++++++ c/src/nodeselect/full/rpc.yml | 120 +++++++ c/src/pay/zksync/rpc.yml | 70 ++++ c/src/signer/pk-signer/rpc.yml | 36 ++ c/src/verifier/btc/rpc.yml | 36 ++ c/src/verifier/eth1/basic/rpc.yml | 5 + 7 files changed, 917 insertions(+) create mode 100644 c/src/api/eth1/rpc.yml create mode 100644 c/src/core/client/rpc.yml create mode 100644 c/src/nodeselect/full/rpc.yml create mode 100644 c/src/pay/zksync/rpc.yml create mode 100644 c/src/signer/pk-signer/rpc.yml create mode 100644 c/src/verifier/btc/rpc.yml create mode 100644 c/src/verifier/eth1/basic/rpc.yml diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml new file mode 100644 index 000000000..be07768f5 --- /dev/null +++ b/c/src/api/eth1/rpc.yml @@ -0,0 +1,544 @@ +in3: + + in3_abiEncode: + descr: based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. + params: + signature: + type: string + descr: the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. + params: + type: array + descr: a array of arguments. the number of arguments must match the arguments in the signature. + returns: + type: hex + descr: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. + example: + request: + - "getBalance(address)" + - ["0x1234567890123456789012345678901234567890"] + response: "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" + + in3_abiDecode: + descr: based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. + params: + signature: + type: string + descr: the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. + data: + type: hex + descr: the data to decode (usually the result of a eth_call) + returns: + type: array + descr: a array (if more then one arguments in the result-type) or the the value after decodeing. + example: + request: + - (address,uint256) + - "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005" + response: + - "0x1234567890123456789012345678901234567890" + - "0x05" + + in3_checksumAddress: + descr: Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) + params: + address: + descr: the address to convert. + type: address + useChainId: + descr: if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) + type: bool + optional: true + returns: + descr: the address-string using the upper/lowercase hex characters. + example: + request: + - "0x1fe2e9bf29aa1938859af64c413361227d04059a" + - false + response: "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" + + + in3_ens: + descr: | + resolves a ens-name. + the domain names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. + For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. + params: + name: + descr: the domain name UTS46 compliant string. + type: string + field: + descr: the required data, which could be one of ( `addr` - the address, `resolver` - the address of the resolver, `hash` - the namehash, `owner` - the owner of the domain) + type: string + optional: true + default: addr + returns: + descr: the value of the specified field + example: + request: + - cryptokitties.eth + - addr + response: "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" + + + + + in3_toWei: + descr: converts the given value into wei. + params: + value: + descr: the value, which may be floating number as string + type: string or uint + example: "0.9" + unit: + descr: the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + type: string + optional: true + default: eth + returns: + descr: the value in wei as hex. + example: + request: + - "20.0009123" + - eth + response: "0x01159183c4793db800" + + + in3_fromWei: + descr: converts a given uint (also as hex) with a wei-value into a specified unit. + params: + value: + descr: the value in wei + type: uint or bytes + example: "0x234324abdef" + unit: + descr: the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + type: string + digits: + descr: fix number of digits after the comma. If left out, only as many as needed will be included. + type: uint + optional: true + returns: + descr: the value as string. + example: + request: + - "0x234324abadefdef" + - eth + - 3 + response: "0.158" + + in3_pk2address: + descr: extracts the address from a private key. + params: + pk: + descr: the 32 bytes private key as hex. + type: bytes32 + returns: + descr: the address + example: + request: + - "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a" + response: "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" + + in3_pk2public: + descr: extracts the public key from a private key. + params: + pk: + descr: the 32 bytes private key as hex. + type: bytes32 + returns: + descr: the public key as 64 bytes + example: + request: + - "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a" + response: "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f78186577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" + + in3_ecrecover: + descr: extracts the public key and address from signature. + params: + msg: + descr: the message the signature is based on. + type: hex + sig: + descr: the 65 bytes signature as hex. + type: bytes + sigtype: + descr: "the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw`" + type: string + default: raw + optional: true + returns: + descr: the extracted public key and address + type: + publicKey: + descr: the public Key of the signer (64 bytes) + type: bytes + address: + descr: the address + type: address + example: + request: + - "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999" + - "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c" + - hash + response: + publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" + address: "0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4" + + + in3_prepareTx: + descr: prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. + params: + tx: + descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + type: + to: + descr: receipient of the transaction. + type: address + from: + descr: sender of the address (if not sepcified, the first signer will be the sender) + type: address + value: + descr: value in wei to send + type: uint + optional: true + gas: + descr: the gas to be send along + type: uint + optional: true + default: 21000 + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + optional: true + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + optional: true + + returns: + descr: the unsigned raw transaction as hex. + example: + request: + - to: "0x63f666a23cbd135a91187499b5cc51d589c302a0" + value: "0x100000000" + from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f" + response: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080" + + in3_signTx: + descr: signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. + params: + tx: + descr: the raw unsigned transactiondata + type: hex + from: + descr: the account to sign + type: address + + returns: + descr: the raw transaction with signature. + example: + request: + - "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080" + - "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f" + response: "0xf86980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a08501000000008026a03c5b094078383f3da3f65773ab1314e89ee76bc41f827f2ef211b2d3449e4435a077755f8d9b32966e1ad8f6c0e8c9376a4387ed237bdbf2db6e6b94016407e276" + + in3_signData: + descr: signs the given data. + params: + msg: + descr: the message to sign. + type: hex + account: + descr: the account to sign if the account is a bytes32 it will be used as private key + type: address | bytes32 + msgType: + descr: "the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data)" + type: string + default: raw + optional: true + + returns: + descr: the signature + type: + message: + descr: original message used + type: bytes + messageHash: + descr: the hash the signature is based on + type: bytes32 + signature: + descr: the signature (65 bytes) + type: bytes + r: + descr: the x-value of the EC-Point + type: bytes32 + s: + descr: the y-value of the EC-Point + type: bytes32 + v: + descr: the recovery value (0|1) + 27 + type: byte + + example: + request: + - "0x0102030405060708090a0b0c0d0e0f" + - "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852" + - raw + response: + message: "0x0102030405060708090a0b0c0d0e0f" + messageHash: "0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67" + signature: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b" + r: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579" + s: "0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152" + v: 27 + + in3_decryptKey: + descr: decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. + params: + key: + descr: Keydata as object as defined in the keystorefile + type: object + passphrase: + descr: the password to decrypt it. + type: string + + returns: + descr: a raw private key (32 bytes) + example: + request: + - version: 3, + id: "f6b5c0b1-ba7a-4b67-9086-a01ea54ec638" + address: "08aa30739030f362a8dd597fd3fcde283e36f4a1" + crypto: + ciphertext: "d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d" + cipherparams: + iv: "415440d2b1d6811d5c8a3f4c92c73f49" + cipher: "aes-128-ctr" + kdf: pbkdf2 + kdfparams: + dklen: 32 + salt: "691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d" + c: 16384 + prf: hmac-sha256 + mac: "de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610" + - test + response: "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" + + in3_cacheClear: + descr: clears the incubed cache (usually found in the .in3-folder) + returns: + descr: true indicating the success + example: + request: [] + response: true + + in3_nodeList: + descr: clears the incubed cache (usually found in the .in3-folder) + params: + limit: + descr: if the number is defined and >0 this method will return a partial nodeList limited to the given number. + type: uint + optional: true + seed: + descr: this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. + type: bytes32 + optional: true + addresses: + descr: a optional array of addresses of signers the nodeList must include. + type: address[] + optional: true + + returns: + descr: the current nodelist + type: + nodes: + descr: a array of node definitions. + type: + url: + descr: the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. + type: string + address: + descr: the address of the signer + type: address + index: + descr: the index within the nodeList of the contract + type: uint + deposit: + descr: the stored deposit + type: uint + props: + descr: the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) + type: uint + timeout: + descr: the time in seconds describing how long the deposit would be locked when trying to unregister a node. + type: uint + registerTime: + descr: unix timestamp in seconds when the node has registered. + type: uint + weight: + descr: the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. + type: uint + proofHash: + descr: | + a hash value containing the above values. + This hash is explicitly stored in the contract, which enables the client to have only one merkle proof + per node instead of verifying each property as its own storage value. + The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` + type: bytes32 + contract: + descr: the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. + type: address + registryId: + descr: the registryId (32 bytes) of the contract, which is there to verify the correct contract. + type: bytes32 + lastBlockNumber: + descr: the blockNumber of the last change of the list (usually the last event). + type: uint + totalServer: + descr: the total numbers of nodes. + type: uint + + proof: + descr: | + if proof is requested, the proof will have the type `accountProof`. In the proof-section only the storage-keys of the `proofHash` will be included. + The required storage keys are calcualted : + + - `0x00` - the length of the nodeList or total numbers of nodes. + - `0x01` - the registryId + - per node : ` 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 + index * 5 + 4` + + The blockNumber of the proof must be the latest final block (`latest`- minBlockHeight) and always greater or equal to the `lastBlockNumber` + + #### Partial NodeLists + + if the client requests a partial nodeList and the given limit is smaller then the total amount of nodes, the server needs to pick nodes in a deterministic way. This is done by using the given seed. + + 1. add all required addresses (if any) to the list. + 2. iterate over the indexes until the limit is reached: + + ```ts + function createIndexes(total: number, limit: number, seed: Buffer): number[] { + const result: number[] = [] // the result as a list of indexes + let step = seed.readUIntBE(0, 6) // first 6 bytes define the step size + let pos = seed.readUIntBE(6, 6) % total // next 6 bytes define the offset + while (result.length < limit) { + if (result.indexOf(pos) >= 0) { // if the index is already part of the result + seed = keccak256(seed) // we create a new seed by hashing the seed. + step = seed.readUIntBE(0, 6) // and change the step-size + } + else + result.push(pos) + pos = (pos + step) % total // use the modulo operator to calculate the next position. + } + return result + } + ```` + type: + type: + descr: the proofType + type: "accountProof" + block: + descr: the serialized blockheader of the latest final block + type: bytes + signatures: + descr: a array of signatures from the signers (if requested) of the above block. + type: bytes[] + accounts: + descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. + type: + "": + descr: The Account of the data-contract. + type: + address: + descr: the address of the account + type: address + balance: + descr: current Balance + type: uint + codeHash: + descr: hash of the contract code + type: bytes32 + nonce: + descr: nonce of the account + type: uint + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + type: bytes[] + storageProof: + descr: Array of Proofs for all required storage values + type: + key: + descr: the storage key (or hash) + type: uint + value: + descr: the storage value + type: bytes32 + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes[] + example: + request: + - 2 + - "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b" + - [] + response: + totalServers: 5 + contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + lastBlockNumber: 8669495 + nodes: + - url: "https://in3-v2.slock.it/mainnet/nd-3" + address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" + index: 2 + deposit: "10000000000000000" + props: 29 + timeout: 3600 + registerTime: 1570109570 + weight: 2000 + proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" + - url: "https://in3-v2.slock.it/mainnet/nd-5" + address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" + index: 4 + deposit: "10000000000000000" + props: 29 + timeout: 3600 + registerTime: 1570109690 + weight: 2000 + proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" + in3: + proof: + type: accountProof + block: "0xf9021ca01...." + accounts: + "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5": + address: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + balance: "0xb1a2bc2ec50000" + codeHash: "0x18e64869905158477a607a68e9c0074d78f56a9dd5665a5254f456f89d5be398" + nonce: "0x1" + storageHash: "0x4386ec93bd665ea07d7ed488e8b495b362a31dc4100cf762b22f4346ee925d1f" + accountProof: + - "0xf90211a0e822..." + - "0xf90211a0f6d0..." + - "0xf90211a04d7b..." + - "0xf90211a0e749..." + - "0xf90211a059cb..." + - "0xf90211a0568f..." + - "0xf8d1a0ac2433..." + - "0xf86d9d33b981..." + storageProof: + - key: "0x0" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xe2a0200decd9548b62a...05" + value: "0x5" + - key: "0x1" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xf843a0200e2d5276120...423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + value: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml new file mode 100644 index 000000000..cc5d39790 --- /dev/null +++ b/c/src/core/client/rpc.yml @@ -0,0 +1,106 @@ +in3: + descr: | + There are also some Incubed specific rpc-methods, which will help the clients to bootstrap and update the nodeLists. + + + The incubed client itself offers special RPC-Methods, which are mostly handled directly inside the client: + + # config + config: + + chainId: + type: uint | string + descr: the chainId or the name of a known chain (`mainnet`,`goerli`,`ewc`,`btc` or `ipfs`). It defines the nodelist to connect to. + example: goerli + optional: true + default: mainnet + + finality: + type: uint | string + descr: the number in percent needed in order reach finality (% of signature of the validators). + example: 50 + optional: true + default: 0 + + includeCode: + type: bool + descr: if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. + example: true + optional: true + default: false + + maxAttempts: + type: uint + descr: max number of attempts in case a response is rejected. + example: 1 + optional: true + default: 7 + + keepIn3: + type: bool + descr: if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. + example: true + optional: true + default: false + + useBinary: + type: bool + descr: if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. + example: true + optional: true + default: false + + experimental: + type: bool + descr: iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. + example: true + optional: true + default: false + + timeout: + descr: specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. + type: uint + optional: true + example: 100000 + default: 20000 + + proof: + descr: if true the nodes should send a proof of the response. If set to none, verification is turned off completly. + type: string (none,standard,full) + optional: true + example: none + default: standard + + replaceLatestBlock: + descr: if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. + type: uint + optional: true + example: 6 + + + # rpc-commands + + in3_config: + descr: changes the configuration of a client. The configuration is passed as the first param and may contain only the values to change. + params: + config: + descr: a Object with config-params. + + returns: + descr: an boolean confirming that the config has changed. + example: + request: + - chainId: "0x5" + maxAttempts: 4 + nodeLimit: 10 + nodes: + "0x1": + nodeList: + - address: "0x1234567890123456789012345678901234567890" + url: "https://mybootnode-A.com" + props: "0xFFFF" + - address: "0x1234567890123456789012345678901234567890" + url: "https://mybootnode-B.com" + props: "0xFFFF" + response: true + diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml new file mode 100644 index 000000000..0fcc06203 --- /dev/null +++ b/c/src/nodeselect/full/rpc.yml @@ -0,0 +1,120 @@ +in3: + + # config + config: + autoUpdateList: + type: bool + optional: true + descr: if true the nodelist will be automaticly updated if the lastBlock is newer. + example: true + default: true + + signatureCount: + descr: number of signatures requested in order to verify the blockhash. + type: uint + optional: true + example: 2 + default: 1 + + bootWeights: + descr: if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. + type: bool + optional: true + example: true + default: true + + useHttp: + descr: if true the client will try to use http instead of https. + type: bool + optional: true + example: true + default: false + + minDeposit: + descr: min stake of the server. Only nodes owning at least this amount will be chosen. + type: uint + optional: true + + nodeProps: + descr: used to identify the capabilities of the node. + type: uint + optional: true + example: 0xffff + + requestCount: + descr: the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. + type: uint + optional: true + example: 3 + default: 2 + + rpc: + descr: url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. + type: string + optional: true + + nodes: + descr: defining the nodelist. collection of JSON objects with chain Id (hex string) as key. + optional: true + example: + "0x1": + nodeList: [] + type: + contract: + descr: address of the registry contract. (This is the data-contract!) + type: address + + whiteListContract: + descr: address of the whiteList contract. This cannot be combined with whiteList! + type: address + optional: true + + whiteList: + descr: manual whitelist. + type: address[] + optional: true + + registryId: + descr: identifier of the registry. + type: bytes32 + + needsUpdate: + descr: if set, the nodeList will be updated before next request. + type: bool + optional: true + + avgBlockTime: + descr: average block time (seconds) for this chain. + type: uint + optional: true + + verifiedHashes: + descr: if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. + optional: true + type: + block: + descr: block number + type: uint + hash: + descr: verified hash corresponding to block number. + type: bytes32 + + nodeList: + descr: manual nodeList. As Value a array of Node-Definitions is expected. + optional: true + type: + url: + descr: URL of the node. + type: string + address: + descr: address of the node + type: string + props: + descr: used to identify the capabilities of the node (defaults to 0xFFFF). + type: uint + + + + + + diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml new file mode 100644 index 000000000..f5b22d507 --- /dev/null +++ b/c/src/pay/zksync/rpc.yml @@ -0,0 +1,70 @@ +zksync: + descr: | + *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* + + the zksync-plugin is able to handle operations to use [zksync](https://zksync.io/) like deposit transfer or withdraw. Also see the #in3-config on how to configure the zksync-server or account. + + Also in order to sign messages you need to set a signer! + + All zksync-methods can be used with `zksync_` or `zk_` prefix. + + # config + config: + + zksync: + descr: configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + type: + provider_url: + descr: url of the zksync-server (if not defined it will be choosen depending on the chain) + type: string + optional: true + default: https://api.zksync.io/jsrpc + + account: + descr: the account to be used. if not specified, the first signer will be used. + type: address + optional: true + + sync_key: + descr: the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. + type: bytes32 + optional: true + + main_contract: + descr: address of the main contract- If not specified it will be taken from the server. + type: address + optional: true + + signer_type: + descr: type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. + type: string + optional: true + default: pk + + musig_pub_keys: + descr: concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. + type: bytes + optional: true + + musig_urls: + descr: a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. + type: string[] + optional: true + + create2: + descr: create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + optional: true + type: + creator: + descr: The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory ) + type: address + saltarg: + descr: a salt-argument, which will be added to the pubkeyhash and create the create2-salt. + type: bytes32 + codehash: + descr: the hash of the actual deploy-tx including the constructor-arguments. + type: bytes32 + + + + diff --git a/c/src/signer/pk-signer/rpc.yml b/c/src/signer/pk-signer/rpc.yml new file mode 100644 index 000000000..14c9dc6a3 --- /dev/null +++ b/c/src/signer/pk-signer/rpc.yml @@ -0,0 +1,36 @@ +in3: + + # config + config: + + key: + type: bytes32 + descr: the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + example: "0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" + optional: true + + pk: + type: bytes32|bytes32[] + descr: registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + example: ["0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe"] + optional: true + + # RPC + in3_addRawKey: + descr: adds a raw private key as signer, which allows signing transactions. + params: + pk: + descr: the 32byte long private key as hex string. + type: bytes32 + returns: + descr: the address of given key. + type: address + example: + request: + - "0x1234567890123456789012345678901234567890123456789012345678901234" + response: "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + + + + + diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml new file mode 100644 index 000000000..59aa70545 --- /dev/null +++ b/c/src/verifier/btc/rpc.yml @@ -0,0 +1,36 @@ +btc: + descr: | + *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* + + For bitcoin incubed follows the specification as defined in [https://bitcoincore.org/en/doc/0.18.0/](https://bitcoincore.org/en/doc/0.18.0/). + Internally the in3-server will add proofs as part of the responses. The proof data differs between the methods. You will read which proof data will be provided and how the data can be used to prove the result for each method. + + Proofs will add a special `in3`-section to the response containing a `proof`- object. This object will contain parts or all of the following properties: + + * **block** + * **final** + * **txIndex** + * **merkleProof** + * **cbtx** + * **cbtxMerkleProof** + + # config + config: + + btc: + descr: configure the Bitcoin verification + type: + maxDAP: + descr: max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. + type: uint + example: 10 + default: 20 + optional: true + + maxDiff: + descr: max increase (in percent) of the difference between targets when accepting new targets. + type: uint + example: 5 + default: 10 + optional: true + diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml new file mode 100644 index 000000000..bcf5548db --- /dev/null +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -0,0 +1,5 @@ +eth: + + + eth_blockNumber: + descr: gets the current blocknumber \ No newline at end of file From 2a6a50125a29746955b1355020a3096565645335 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:15:12 +0100 Subject: [PATCH 018/221] fix autocomplete --- scripts/_in3.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 6b4cd6f65..4b9a90401 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -47,20 +47,20 @@ subcmds=( 'in3_signData: signs the as passed as argument with the configured signer. optional ' 'in3_cacheClear: clears the local filecache' 'in3_signTx: signs a raw transaction ' - 'zk_deposit: sends a L1-Transaction to add to the deposit ' - 'zk_transfer: transfers the given amount from the configured account to another account in L2 ' - 'zk_withdraw: transfers the given amount from the configured account in L2 to another account in L1 ' - 'zk_set_key: sets the configured key as signer for the account args: ' - 'zk_emergency_withdraw: sends a L1 Tx to withdraw all tokens from L2 ' - 'zk_sync_key: calculates and returns the pk used to sign zksync-tx (using babyjupjup curve)' - 'zk_aggregate_pubkey: calculates the combined musig public key for the concatinated public keys (each with 32 bytes)' - 'zk_pubkeyhash: returns the pubkeyhash of the signer based on the config' - 'zk_pubkey: returns the compact pubkey(32 bytes) of the signer based on the config or from the , if given' - 'zk_account_address: returns address of the zksync-account based on the config' - 'zk_account_info: returns the current balance and state of the account' - 'zk_tokens: returns a list of all available tokens' - 'zk_sign: sign the given with the syncKey. If the -zms and -zmu are passed, it will use musig schnirr sigs to create MPC-Signature' - 'zk_verify: verifies the signature of the ' + 'zksync_deposit: sends a L1-Transaction to add to the deposit ' + 'zksync_transfer: transfers the given amount from the configured account to another account in L2 ' + 'zksync_withdraw: transfers the given amount from the configured account in L2 to another account in L1 ' + 'zksync_set_key: sets the configured key as signer for the account args: ' + 'zksync_emergency_withdraw: sends a L1 Tx to withdraw all tokens from L2 ' + 'zksync_sync_key: calculates and returns the pk used to sign zksync-tx (using babyjupjup curve)' + 'zksync_aggregate_pubkey: calculates the combined musig public key for the concatinated public keys (each with 32 bytes)' + 'zksync_pubkeyhash: returns the pubkeyhash of the signer based on the config' + 'zksync_pubkey: returns the compact pubkey(32 bytes) of the signer based on the config or from the , if given' + 'zksync_account_address: returns address of the zksync-account based on the config' + 'zksync_account_info: returns the current balance and state of the account' + 'zksync_tokens: returns a list of all available tokens' + 'zksync_sign: sign the given with the syncKey. If the -zms and -zmu are passed, it will use musig schnirr sigs to create MPC-Signature' + 'zksync_verify: verifies the signature of the ' 'iamo_add_user: adds a new user to the vault-api' 'iamo_zk_add_wallet: add a json-definition of a mutisig.' 'iamo_zk_create_wallet: creates a multisig-definition based on the Approver-API (-zmu) ....' @@ -118,8 +118,8 @@ args=( '-zc2[zksync create2 arguments in the form ::. if set the account type is also changed to create2]:zc2:()' '-zms[public keys of a musig schnorr signatures to sign with]:zms:()' '-zmu[url for signing service matching the first remote public key]:zmu:(http\://localhost\:8080)' - '-zvpm[method for calling to verify the proof in server mode]:zvpm:(iamo_zk_verify_signatures)' - '-zcpm[method for calling to create the proof]:zcpm:(iamo_zk_create_signatures)' + '-zvpm[method for calling to verify the proof in server mode]:zvpm:(iamo_zksync_verify_signatures)' + '-zcpm[method for calling to create the proof]:zcpm:(iamo_zksync_create_signatures)' '-idk[iamo device key]:idk:()' '-imc[the master copy address to be used]:imc:()' '-if[iamo factory address]:if:()' From 1612db5c630dfad6770a05ecf3f11ec1adcf0171 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 21:33:22 +0100 Subject: [PATCH 019/221] fix signer --- c/src/api/eth1/rpc.yml | 210 -------------------- c/src/nodeselect/full/nodeselect_def.c | 2 +- c/src/nodeselect/full/rpc.yml | 264 ++++++++++++++++++++++++- c/src/signer/pk-signer/signer.c | 5 +- 4 files changed, 267 insertions(+), 214 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index be07768f5..388f515c9 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -332,213 +332,3 @@ in3: request: [] response: true - in3_nodeList: - descr: clears the incubed cache (usually found in the .in3-folder) - params: - limit: - descr: if the number is defined and >0 this method will return a partial nodeList limited to the given number. - type: uint - optional: true - seed: - descr: this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. - type: bytes32 - optional: true - addresses: - descr: a optional array of addresses of signers the nodeList must include. - type: address[] - optional: true - - returns: - descr: the current nodelist - type: - nodes: - descr: a array of node definitions. - type: - url: - descr: the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. - type: string - address: - descr: the address of the signer - type: address - index: - descr: the index within the nodeList of the contract - type: uint - deposit: - descr: the stored deposit - type: uint - props: - descr: the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - type: uint - timeout: - descr: the time in seconds describing how long the deposit would be locked when trying to unregister a node. - type: uint - registerTime: - descr: unix timestamp in seconds when the node has registered. - type: uint - weight: - descr: the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. - type: uint - proofHash: - descr: | - a hash value containing the above values. - This hash is explicitly stored in the contract, which enables the client to have only one merkle proof - per node instead of verifying each property as its own storage value. - The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` - type: bytes32 - contract: - descr: the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. - type: address - registryId: - descr: the registryId (32 bytes) of the contract, which is there to verify the correct contract. - type: bytes32 - lastBlockNumber: - descr: the blockNumber of the last change of the list (usually the last event). - type: uint - totalServer: - descr: the total numbers of nodes. - type: uint - - proof: - descr: | - if proof is requested, the proof will have the type `accountProof`. In the proof-section only the storage-keys of the `proofHash` will be included. - The required storage keys are calcualted : - - - `0x00` - the length of the nodeList or total numbers of nodes. - - `0x01` - the registryId - - per node : ` 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 + index * 5 + 4` - - The blockNumber of the proof must be the latest final block (`latest`- minBlockHeight) and always greater or equal to the `lastBlockNumber` - - #### Partial NodeLists - - if the client requests a partial nodeList and the given limit is smaller then the total amount of nodes, the server needs to pick nodes in a deterministic way. This is done by using the given seed. - - 1. add all required addresses (if any) to the list. - 2. iterate over the indexes until the limit is reached: - - ```ts - function createIndexes(total: number, limit: number, seed: Buffer): number[] { - const result: number[] = [] // the result as a list of indexes - let step = seed.readUIntBE(0, 6) // first 6 bytes define the step size - let pos = seed.readUIntBE(6, 6) % total // next 6 bytes define the offset - while (result.length < limit) { - if (result.indexOf(pos) >= 0) { // if the index is already part of the result - seed = keccak256(seed) // we create a new seed by hashing the seed. - step = seed.readUIntBE(0, 6) // and change the step-size - } - else - result.push(pos) - pos = (pos + step) % total // use the modulo operator to calculate the next position. - } - return result - } - ```` - type: - type: - descr: the proofType - type: "accountProof" - block: - descr: the serialized blockheader of the latest final block - type: bytes - signatures: - descr: a array of signatures from the signers (if requested) of the above block. - type: bytes[] - accounts: - descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. - type: - "": - descr: The Account of the data-contract. - type: - address: - descr: the address of the account - type: address - balance: - descr: current Balance - type: uint - codeHash: - descr: hash of the contract code - type: bytes32 - nonce: - descr: nonce of the account - type: uint - storageHash: - descr: MerkleRoot of the Storage Trie - type: bytes32 - accountProof: - descr: MerkleProof of this account-node - type: bytes[] - storageProof: - descr: Array of Proofs for all required storage values - type: - key: - descr: the storage key (or hash) - type: uint - value: - descr: the storage value - type: bytes32 - proof: - descr: the merkleProof of the value down to the storageHash as MerkleRoot - type: bytes[] - example: - request: - - 2 - - "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b" - - [] - response: - totalServers: 5 - contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" - registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - lastBlockNumber: 8669495 - nodes: - - url: "https://in3-v2.slock.it/mainnet/nd-3" - address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" - index: 2 - deposit: "10000000000000000" - props: 29 - timeout: 3600 - registerTime: 1570109570 - weight: 2000 - proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" - - url: "https://in3-v2.slock.it/mainnet/nd-5" - address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" - index: 4 - deposit: "10000000000000000" - props: 29 - timeout: 3600 - registerTime: 1570109690 - weight: 2000 - proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" - in3: - proof: - type: accountProof - block: "0xf9021ca01...." - accounts: - "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5": - address: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" - balance: "0xb1a2bc2ec50000" - codeHash: "0x18e64869905158477a607a68e9c0074d78f56a9dd5665a5254f456f89d5be398" - nonce: "0x1" - storageHash: "0x4386ec93bd665ea07d7ed488e8b495b362a31dc4100cf762b22f4346ee925d1f" - accountProof: - - "0xf90211a0e822..." - - "0xf90211a0f6d0..." - - "0xf90211a04d7b..." - - "0xf90211a0e749..." - - "0xf90211a059cb..." - - "0xf90211a0568f..." - - "0xf8d1a0ac2433..." - - "0xf86d9d33b981..." - storageProof: - - key: "0x0" - proof: - - "0xf90211a0ccb6d2d5786..." - - "0xf871808080808080800..." - - "0xe2a0200decd9548b62a...05" - value: "0x5" - - key: "0x1" - proof: - - "0xf90211a0ccb6d2d5786..." - - "0xf871808080808080800..." - - "0xf843a0200e2d5276120...423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - value: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - diff --git a/c/src/nodeselect/full/nodeselect_def.c b/c/src/nodeselect/full/nodeselect_def.c index 971b15f94..abaa49b00 100644 --- a/c/src/nodeselect/full/nodeselect_def.c +++ b/c/src/nodeselect/full/nodeselect_def.c @@ -59,7 +59,7 @@ static in3_ret_t rpc_verify(in3_nodeselect_def_t* data, in3_vctx_t* vc) { // do we have a result? if not it is a valid error-response if (!vc->result) return IN3_OK; - if (strcmp(vc->method, "in3_nodeList") == 0) { + if (VERIFY_RPC("in3_nodeList")) { d_token_t* params = d_get(vc->request, K_PARAMS); return eth_verify_in3_nodelist(data, vc, d_get_int_at(params, 0), d_get_bytes_at(params, 1), d_get_at(params, 2)); } diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 0fcc06203..74091b754 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -113,8 +113,270 @@ in3: descr: used to identify the capabilities of the node (defaults to 0xFFFF). type: uint + # Verified RPCs + in3_nodeList: + descr: clears the incubed cache (usually found in the .in3-folder) + params: + limit: + descr: if the number is defined and >0 this method will return a partial nodeList limited to the given number. + type: uint + optional: true + seed: + descr: this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. + type: bytes32 + optional: true + addresses: + descr: a optional array of addresses of signers the nodeList must include. + type: address[] + optional: true + + returns: + descr: the current nodelist + type: + nodes: + descr: a array of node definitions. + type: + url: + descr: the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. + type: string + address: + descr: the address of the signer + type: address + index: + descr: the index within the nodeList of the contract + type: uint + deposit: + descr: the stored deposit + type: uint + props: + descr: the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) + type: uint + timeout: + descr: the time in seconds describing how long the deposit would be locked when trying to unregister a node. + type: uint + registerTime: + descr: unix timestamp in seconds when the node has registered. + type: uint + weight: + descr: the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. + type: uint + proofHash: + descr: | + a hash value containing the above values. + This hash is explicitly stored in the contract, which enables the client to have only one merkle proof + per node instead of verifying each property as its own storage value. + The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` + type: bytes32 + contract: + descr: the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. + type: address + registryId: + descr: the registryId (32 bytes) of the contract, which is there to verify the correct contract. + type: bytes32 + lastBlockNumber: + descr: the blockNumber of the last change of the list (usually the last event). + type: uint + totalServer: + descr: the total numbers of nodes. + type: uint + + proof: + descr: | + if proof is requested, the proof will have the type `accountProof`. In the proof-section only the storage-keys of the `proofHash` will be included. + The required storage keys are calcualted : + + - `0x00` - the length of the nodeList or total numbers of nodes. + - `0x01` - the registryId + - per node : ` 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 + index * 5 + 4` + + The blockNumber of the proof must be the latest final block (`latest`- minBlockHeight) and always greater or equal to the `lastBlockNumber` + + #### Partial NodeLists + + if the client requests a partial nodeList and the given limit is smaller then the total amount of nodes, the server needs to pick nodes in a deterministic way. This is done by using the given seed. + + 1. add all required addresses (if any) to the list. + 2. iterate over the indexes until the limit is reached: + + ```ts + function createIndexes(total: number, limit: number, seed: Buffer): number[] { + const result: number[] = [] // the result as a list of indexes + let step = seed.readUIntBE(0, 6) // first 6 bytes define the step size + let pos = seed.readUIntBE(6, 6) % total // next 6 bytes define the offset + while (result.length < limit) { + if (result.indexOf(pos) >= 0) { // if the index is already part of the result + seed = keccak256(seed) // we create a new seed by hashing the seed. + step = seed.readUIntBE(0, 6) // and change the step-size + } + else + result.push(pos) + pos = (pos + step) % total // use the modulo operator to calculate the next position. + } + return result + } + ```` + type: + type: + descr: the proofType + type: "accountProof" + block: + descr: the serialized blockheader of the latest final block + type: bytes + signatures: + descr: a array of signatures from the signers (if requested) of the above block. + type: bytes[] + accounts: + descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. + type: + "": + descr: The Account of the data-contract. + type: + address: + descr: the address of the account + type: address + balance: + descr: current Balance + type: uint + codeHash: + descr: hash of the contract code + type: bytes32 + nonce: + descr: nonce of the account + type: uint + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + type: bytes[] + storageProof: + descr: Array of Proofs for all required storage values + type: + key: + descr: the storage key (or hash) + type: uint + value: + descr: the storage value + type: bytes32 + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes[] + example: + request: + - 2 + - "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b" + - [] + response: + totalServers: 5 + contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + lastBlockNumber: 8669495 + nodes: + - url: "https://in3-v2.slock.it/mainnet/nd-3" + address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" + index: 2 + deposit: "10000000000000000" + props: 29 + timeout: 3600 + registerTime: 1570109570 + weight: 2000 + proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" + - url: "https://in3-v2.slock.it/mainnet/nd-5" + address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" + index: 4 + deposit: "10000000000000000" + props: 29 + timeout: 3600 + registerTime: 1570109690 + weight: 2000 + proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" + in3: + proof: + type: accountProof + block: "0xf9021ca01...." + accounts: + "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5": + address: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + balance: "0xb1a2bc2ec50000" + codeHash: "0x18e64869905158477a607a68e9c0074d78f56a9dd5665a5254f456f89d5be398" + nonce: "0x1" + storageHash: "0x4386ec93bd665ea07d7ed488e8b495b362a31dc4100cf762b22f4346ee925d1f" + accountProof: + - "0xf90211a0e822..." + - "0xf90211a0f6d0..." + - "0xf90211a04d7b..." + - "0xf90211a0e749..." + - "0xf90211a059cb..." + - "0xf90211a0568f..." + - "0xf8d1a0ac2433..." + - "0xf86d9d33b981..." + storageProof: + - key: "0x0" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xe2a0200decd9548b62a...05" + value: "0x5" + - key: "0x1" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xf843a0200e2d5276120...423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + value: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - + in3_sign: + descr: | + requests a signed blockhash from the node. + In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers + and the processising nodes will then aquire the signatures with this method from the other nodes. + + Since each node has a risk of signing a wrong blockhash and getting convicted and losing its deposit, + per default nodes will and should not sign blockHash of the last `minBlockHeight` (default: 6) blocks! + params: + blocks: + descr: array of requested blocks. + type: + blockNumber: + descr: the blockNumber to sign + type: uint + hash: + descr: the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. + type: bytes32 + optional: true + + returns: + descr: the Array with signatures of all the requires blocks. + type: + blockHash: + descr: the blockhash which was signed. + type: bytes32 + block: + descr: the blocknumber + type: uint + r: + descr: r-value of the signature + type: bytres32 + s: + descr: s-value of the signature + type: bytes32 + v: + descr: v-value of the signature + type: byte + msgHash: + descr: the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` + type: bytes32 + example: + request: + - blockNumber: 8770580 + response: + - blockHash: "0xd8189793f64567992eaadefc51834f3d787b03e9a6850b8b9b8003d8d84a76c8" + block: 8770580 + r: "0x954ed45416e97387a55b2231bff5dd72e822e4a5d60fa43bc9f9e49402019337" + s: "0x277163f586585092d146d0d6885095c35c02b360e4125730c52332cf6b99e596" + v: 28 + msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" + + diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index 55f132276..dc77de8b9 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -204,8 +204,9 @@ static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { } case PLGN_ACT_RPC_HANDLE: { - TRY_RPC("in3_addRawKey", add_raw_key(action_ctx)) - TRY_RPC("eth_accounts", eth_accounts(action_ctx)) + in3_rpc_handle_ctx_t* ctx = action_ctx; + TRY_RPC("in3_addRawKey", add_raw_key(ctx)) + TRY_RPC("eth_accounts", eth_accounts(ctx)) return IN3_EIGNORE; } From 86be6f577e2c28778daa7f00843564b920aed425 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 23 Mar 2021 22:02:36 +0100 Subject: [PATCH 020/221] add web3_clientVersion --- c/src/api/eth1/rpc_api.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 3d1771d04..5298c8e2d 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -35,6 +35,7 @@ #include "../../core/client/keys.h" #include "../../core/client/plugin.h" #include "../../core/client/request_internal.h" +#include "../../core/client/version.h" #include "../../core/util/debug.h" #include "../../core/util/log.h" #include "../../core/util/mem.h" @@ -156,6 +157,11 @@ static in3_ret_t in3_sha256(in3_rpc_handle_ctx_t* ctx) { sha256_Final(&c, hash); return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); } +static in3_ret_t web3_clientVersion(in3_rpc_handle_ctx_t* ctx) { + if (ctx->req->client->chain.chain_id == CHAIN_ID_LOCAL) return IN3_EIGNORE; + + return in3_rpc_handle_with_string(ctx, "\"Incubed/" IN3_VERSION "\""); +} static const char* UNITS[] = { "wei", "", "kwei", "\x03", @@ -555,6 +561,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("web3_sha3", in3_sha3(ctx)) TRY_RPC("keccak", in3_sha3(ctx)) TRY_RPC("sha256", in3_sha256(ctx)) + TRY_RPC("web3_clientVersion", web3_clientVersion(ctx)) if (strncmp(ctx->method, "in3_", 4)) return IN3_EIGNORE; // shortcut From 7c207fc90ff9ae3f63f458945d7f5fc2bceb41bb Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 07:58:00 +0100 Subject: [PATCH 021/221] formating --- c/src/api/eth1/rpc_api.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 5298c8e2d..e7fa117c0 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -158,10 +158,12 @@ static in3_ret_t in3_sha256(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); } static in3_ret_t web3_clientVersion(in3_rpc_handle_ctx_t* ctx) { - if (ctx->req->client->chain.chain_id == CHAIN_ID_LOCAL) return IN3_EIGNORE; - - return in3_rpc_handle_with_string(ctx, "\"Incubed/" IN3_VERSION "\""); + // for local chains, we return the client version of rpc endpoint. + return ctx->req->client->chain.chain_id == CHAIN_ID_LOCAL + ? IN3_EIGNORE + : in3_rpc_handle_with_string(ctx, "\"Incubed/" IN3_VERSION "\""); } + static const char* UNITS[] = { "wei", "", "kwei", "\x03", From af05ecc95c579447eb3a8c4b4bb608dd4032b457 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 07:58:28 +0100 Subject: [PATCH 022/221] added eth_nano --- c/src/api/eth1/rpc.yml | 4 + c/src/nodeselect/full/rpc.yml | 121 +++++++++++++++++++++++++++++++ c/src/verifier/eth1/nano/rpc.yml | 28 +++++++ 3 files changed, 153 insertions(+) create mode 100644 c/src/verifier/eth1/nano/rpc.yml diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 388f515c9..845a7b8bf 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -332,3 +332,7 @@ in3: request: [] response: true + web3_clientVersion: + descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. + returns: + descr: in3 + version diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 74091b754..7353c0da3 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -379,4 +379,125 @@ in3: v: 28 msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" + in3_whitelist: + descr: Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. + params: + address: + descr: address of whitelist contract + type: address + returns: + descr: the whitelisted addresses + type: + nodes: + descr: array of whitelisted nodes addresses. + type: address + lastWhiteList: + descr: the blockNumber of the last change of the in3 white list event. + type: uint + contract: + descr: whitelist contract address. + type: address + lastBlockNumber: + descr: the blockNumber of the last change of the list (usually the last event). + type: uint + totalServer: + descr: the total numbers of whitelist nodes. + type: uint + + proof: + descr: | + if proof is requested, the proof will have the type `accountProof`. In the proof-section only the storage-keys of the addresses and the length (`0x0`) will be included. + + The blockNumber of the proof must be the latest final block (`latest`- minBlockHeight) and always greater or equal to the `lastBlockNumber` + + type: + type: + descr: the proofType + type: "accountProof" + block: + descr: the serialized blockheader of the latest final block + type: bytes + signatures: + descr: a array of signatures from the signers (if requested) of the above block. + type: bytes[] + accounts: + descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. + type: + "": + descr: The Account of the data-contract. + type: + address: + descr: the address of the account + type: address + balance: + descr: current Balance + type: uint + codeHash: + descr: hash of the contract code + type: bytes32 + nonce: + descr: nonce of the account + type: uint + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + type: bytes[] + storageProof: + descr: Array of Proofs for all required storage values + type: + key: + descr: the storage key (or hash) + type: uint + value: + descr: the storage value + type: bytes32 + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes[] + + example: + request: + - "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" + response: + totalServers: 2 + contract: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" + lastBlockNumber: 1546354 + nodes: + - "0x1fe2e9bf29aa1938859af64c413361227d04059a" + - "0x45d45e6ff99e6c34a235d263965910298985fcfe" + in3: + proof: + type: accountProof + block: "0xf9021ca01...." + accounts: + "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b": + address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" + balance: "0xb1a2bc2ec50000" + codeHash: "0x18e64869905158477a607a68e9c0074d78f56a9dd5665a5254f456f89d5be398" + nonce: "0x1" + storageHash: "0x4386ec93bd665ea07d7ed488e8b495b362a31dc4100cf762b22f4346ee925d1f" + accountProof: + - "0xf90211a0e822..." + - "0xf90211a0f6d0..." + - "0xf90211a04d7b..." + - "0xf90211a0e749..." + - "0xf90211a059cb..." + - "0xf90211a0568f..." + - "0xf8d1a0ac2433..." + - "0xf86d9d33b981..." + storageProof: + - key: "0x0" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xe2a0200decd9548b62a...05" + value: "0x5" + - key: "0x1" + proof: + - "0xf90211a0ccb6d2d5786..." + - "0xf871808080808080800..." + - "0xf843a0200e2d5276120...423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + value: "0x6aa7bbfbb1778efa33da1ba032cc3a79b9ef57b428441b4de4f1c38c3f258874" diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml new file mode 100644 index 000000000..3d6cc2f85 --- /dev/null +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -0,0 +1,28 @@ +eth: + descr: | + Standard JSON-RPC calls as described in https://eth.wiki/json-rpc/API. + + Whenever a request is made for a response with `verification`: `proof`, the node must provide the proof needed to validate the response result. The proof itself depends on the chain. + + For ethereum, all proofs are based on the correct block hash. That's why verification differentiates between [Verifying the blockhash](poa.html) (which depends on the user consensus) the actual result data. + + There is another reason why the BlockHash is so important. This is the only value you are able to access from within a SmartContract, because the evm supports a OpCode (`BLOCKHASH`), which allows you to read the last 256 blockhashes, which gives us the chance to verify even the blockhash onchain. + + Depending on the method, different proofs are needed, which are described in this document. + + Proofs will add a special in3-section to the response containing a `proof`- object. Each `in3`-section of the response containing proofs has a property with a proof-object with the following properties: + + * **type** `string` (required) - The type of the proof. + Must be one of the these values : `'transactionProof`', `'receiptProof`', `'blockProof`', `'accountProof`', `'callProof`', `'logProof`' + * **block** `string` - The serialized blockheader as hex, required in most proofs. + * **finalityBlocks** `array` - The serialized following blockheaders as hex, required in case of finality asked (only relevant for PoA-chains). The server must deliver enough blockheaders to cover more then 50% of the validators. In order to verify them, they must be linkable (with the parentHash). + * **transactions** `array` - The list of raw transactions of the block if needed to create a merkle trie for the transactions. + * **uncles** `array` - The list of uncle-headers of the block. This will only be set if full verification is required in order to create a merkle tree for the uncles and so prove the uncle_hash. + * **merkleProof** `string[]` - The serialized merkle-nodes beginning with the root-node (depending on the content to prove). + * **merkleProofPrev** `string[]` - The serialized merkle-nodes beginning with the root-node of the previous entry (only for full proof of receipts). + * **txProof** `string[]` - The serialized merkle-nodes beginning with the root-node in order to proof the transactionIndex (only needed for transaction receipts). + * **logProof** [LogProof](#logproof) - The Log Proof in case of a `eth_getLogs`-request. + * **accounts** `object` - A map of addresses and their AccountProof. + * **txIndex** `integer` - The transactionIndex within the block (for transaactions and receipts). + * **signatures** `Signature[]` - Requested signatures. + From 92db7cc397024329a6645548f5100fdb4da2a1b7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 13:20:43 +0100 Subject: [PATCH 023/221] add docu for other eth_methods --- c/src/api/eth1/rpc.yml | 80 ++- c/src/api/eth1/rpc_api.c | 57 +- c/src/signer/pk-signer/rpc.yml | 9 + c/src/verifier/eth1/basic/rpc.yml | 989 +++++++++++++++++++++++++++++- c/src/verifier/eth1/full/rpc.yml | 246 ++++++++ c/src/verifier/eth1/nano/rpc.yml | 188 ++++++ scripts/build_rpc_docu.js | 51 +- 7 files changed, 1574 insertions(+), 46 deletions(-) create mode 100644 c/src/verifier/eth1/full/rpc.yml diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 845a7b8bf..d82368dcf 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -214,6 +214,10 @@ in3: descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` type: uint optional: true + data: + descr: the data-section of the transaction + type: bytes + optional: true returns: descr: the unsigned raw transaction as hex. @@ -332,7 +336,81 @@ in3: request: [] response: true +eth: + web3_clientVersion: descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. returns: - descr: in3 + version + descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. + + keccak: + alias: web3_sha3 + + web3_sha3: + descr: | + Returns Keccak-256 (not the standardized SHA3-256) of the given data. + + See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + returns: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + + sha256: + descr: | + Returns sha-256 of the given data. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + returns: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + + net_version: + descr: the Network Version (currently 1) + returns: + descr: the Version number + + + + eth_sign: + descr: | + The sign method calculates an Ethereum specific signature with: + + ```js + sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). + ``` + + By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + + For the address to sign a signer must be registered. + params: + account: + descr: the account to sign with + type: address + message: + descr: the message to sign + type: bytes + returns: + descr: the signature (65 bytes) for the given message. + example: + request: + - '0x9b2055d370f73ec7d8a03e965129118dc8f5bf83' + - '0xdeadbeaf' + response: '0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b' + + diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index e7fa117c0..67fbc4dcb 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -432,10 +432,11 @@ static in3_ret_t in3_ecrecover(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_sign_data(in3_rpc_handle_ctx_t* ctx) { - bytes_t data = d_to_bytes(d_get_at(ctx->params, 0)); - const bytes_t* pk = d_get_bytes_at(ctx->params, 1); + const is_eth_sign = strcmp(ctx->method, "eth_sign") == 0; + bytes_t data = d_to_bytes(d_get_at(ctx->params, is_eth_sign ? 1 : 0)); + const bytes_t* pk = d_get_bytes_at(ctx->params, is_eth_sign ? 0 : 1); char* sig_type = d_get_string_at(ctx->params, 2); - if (!sig_type) sig_type = "raw"; + if (!sig_type) sig_type = is_eth_sign ? "eth_sign" : "raw"; // if (!pk) return req_set_error(ctx, "Invalid sprivate key! must be 32 bytes long", IN3_EINVAL); if (!data.data) return req_set_error(ctx->req, "Missing message", IN3_EINVAL); @@ -477,28 +478,35 @@ static in3_ret_t in3_sign_data(in3_rpc_handle_ctx_t* ctx) { sc.signature.data[64] += 27; sb_t* sb = in3_rpc_handle_start(ctx); - sb_add_char(sb, '{'); - sb_add_bytes(sb, "\"message\":", &data, 1, false); - sb_add_char(sb, ','); - if (strcmp(sig_type, "raw") == 0) { - bytes32_t hash_val; - bytes_t hash_bytes = bytes(hash_val, 32); - keccak(data, hash_val); - sb_add_bytes(sb, "\"messageHash\":", &hash_bytes, 1, false); + if (is_eth_sign) { + sb_add_rawbytes(sb, "\"0x", sig_bytes, 0); + sb_add_char(sb, '"'); } - else - sb_add_bytes(sb, "\"messageHash\":", &data, 1, false); - sb_add_char(sb, ','); - sb_add_bytes(sb, "\"signature\":", &sig_bytes, 1, false); - sig_bytes = bytes(sc.signature.data, 32); - sb_add_char(sb, ','); - sb_add_bytes(sb, "\"r\":", &sig_bytes, 1, false); - sig_bytes = bytes(sc.signature.data + 32, 32); - sb_add_char(sb, ','); - sb_add_bytes(sb, "\"s\":", &sig_bytes, 1, false); - char v[15]; - sprintf(v, ",\"v\":%d}", (unsigned int) sc.signature.data[64]); - sb_add_chars(sb, v); + else { + sb_add_char(sb, '{'); + sb_add_bytes(sb, "\"message\":", &data, 1, false); + sb_add_char(sb, ','); + if (strcmp(sig_type, "raw") == 0) { + bytes32_t hash_val; + bytes_t hash_bytes = bytes(hash_val, 32); + keccak(data, hash_val); + sb_add_bytes(sb, "\"messageHash\":", &hash_bytes, 1, false); + } + else + sb_add_bytes(sb, "\"messageHash\":", &data, 1, false); + sb_add_char(sb, ','); + sb_add_bytes(sb, "\"signature\":", &sig_bytes, 1, false); + sig_bytes = bytes(sc.signature.data, 32); + sb_add_char(sb, ','); + sb_add_bytes(sb, "\"r\":", &sig_bytes, 1, false); + sig_bytes = bytes(sc.signature.data + 32, 32); + sb_add_char(sb, ','); + sb_add_bytes(sb, "\"s\":", &sig_bytes, 1, false); + char v[15]; + sprintf(v, ",\"v\":%d}", (unsigned int) sc.signature.data[64]); + sb_add_chars(sb, v); + } + _free(sc.signature.data); return in3_rpc_handle_finish(ctx); } @@ -564,6 +572,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("keccak", in3_sha3(ctx)) TRY_RPC("sha256", in3_sha256(ctx)) TRY_RPC("web3_clientVersion", web3_clientVersion(ctx)) + TRY_RPC("eth_sign", in3_sign_data(ctx)) if (strncmp(ctx->method, "in3_", 4)) return IN3_EIGNORE; // shortcut diff --git a/c/src/signer/pk-signer/rpc.yml b/c/src/signer/pk-signer/rpc.yml index 14c9dc6a3..764eae59c 100644 --- a/c/src/signer/pk-signer/rpc.yml +++ b/c/src/signer/pk-signer/rpc.yml @@ -30,7 +30,16 @@ in3: - "0x1234567890123456789012345678901234567890123456789012345678901234" response: "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + eth_accounts: + descr: returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. + returns: + descr: the array of addresses of all registered signers. + example: + response: + - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" + diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index bcf5548db..0d3cd7639 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -1,5 +1,992 @@ eth: + eth_blockNumber: - descr: gets the current blocknumber \ No newline at end of file + descr: | + returns the number of the most recent block. + + See [eth_blockNumber](https://eth.wiki/json-rpc/API#eth_blockNumber) for spec. + + No proof returned, since there is none, but the client should verify the result by comparing it to the current blocks returned from others. + With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. + returns: + descr: the highest known blocknumber + example: + response: "0xb8a2a5" + + eth_getBlockByNumber: + descr: | + returns information about a block by block number. + + See [eth_getBlockByNumber](https://eth.wiki/json-rpc/API#eth_getBlockByNumber) for spec. + params: + blockNumber: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint + fullTx: + descr: if true the full transactions are contained in the result. + type: bool + result: + descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. + type: + number: + descr: the block number. `null` when its pending block. + type: uint + hash: + descr: hash of the block. `null` when its pending block. + type: bytes32 + parentHash: + descr: hash of the parent block. + type: bytes32 + nonce: + descr: hash of the generated proof-of-work. `null` when its pending block. + type: uint64 + sha3Uncles: + descr: SHA3 of the uncles Merkle root in the block. + type: bytes32 + logsBloom: + descr: the bloom filter for the logs of the block. `null` when its pending block. + type: bytes256 + transactionsRoot: + descr: the root of the transaction trie of the block. + type: bytes32 + stateRoot: + descr: the root of the final state trie of the block. + type: bytes32 + receiptsRoot: + descr: the root of the receipts trie of the block. + type: bytes32 + miner: + descr: the address of the beneficiary to whom the mining rewards were given. + type: address + difficulty: + descr: integer of the difficulty for this block. + type: uint + totalDifficulty: + descr: integer of the total difficulty of the chain until this block. + type: uint + extraData: + descr: the "extra data" field of this block. + type: bytes + size: + descr: integer the size of this block in bytes. + type: uint + gasLimit: + descr: the maximum gas allowed in this block. + type: uint + gasUsed: + descr: the total used gas by all transactions in this block. + type: uint + timestamp: + descr: the unix timestamp for when the block was collated. + type: uint + transactions: + descr: Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. + type: transaction[] + uncles: + descr: Array of uncle hashes. + type: bytes32[] + + example: + request: + - latest + - false + response: + author: '0x0000000000000000000000000000000000000000' + difficulty: '0x2' + extraData: '0x696e667572612d696f0000000000000...31570f1e500' + gasLimit: '0x7a1200' + gasUsed: '0x20e145' + hash: '0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585' + logsBloom: '0x000008000000000000...00400100000000080' + miner: '0x0000000000000000000000000000000000000000' + number: '0x449956' + parentHash: '0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694' + receiptsRoot: '0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff' + sealFields: + - '0xa00000000000000000000000000000000000000000000000000000000000000000' + - '0x880000000000000000' + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347' + size: '0x74b' + stateRoot: '0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910' + timestamp: '0x605aec86' + totalDifficulty: '0x6564de' + transactions: + - '0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58' + - '0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641' + - '0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75' + - '0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d' + - '0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5' + - '0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8' + transactionsRoot: '0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc' + uncles: [] + in3: + proof: + type: blockProof + signatures: [] + transactions: + - '0xf8ac830331f78449504f80830186a094f74a...8a83ce8dc' + - '0xf8ac830331f88449504f80830186a094f74a...a81c2f1fee77' + - '0xf8a91e843b9aca008315a92594f0277caffea...c30d64dd139' + - '0xf8c601843b9aca008305573094309906d7b701...62f5e7a2319a' + - '0xf8c680843b9aca008305573094309906d7b701...78289116eac194e' + - '0xf9014b82020a843b9aca0083010f6894786f8d72...b649' + proof: + descr: | + The `eth_getBlockBy...` methods return the Block-Data. + In this case, all we need is somebody verifying the blockhash, which is done by requiring somebody who stored a deposit and would otherwise lose it, to sign this blockhash. + + The verification is then done by simply creating the blockhash and comparing this to the signed one. + + The blockhash is calculated by blockdata with [rlp](https://github.com/ethereum/wiki/wiki/RLP) and hashing it: + + + ```js + blockHeader = rlp.encode([ + bytes32( parentHash ), + bytes32( sha3Uncles ), + address( miner || coinbase ), + bytes32( stateRoot ), + bytes32( transactionsRoot ), + bytes32( receiptsRoot || receiptRoot ), + bytes256( logsBloom ), + uint( difficulty ), + uint( number ), + uint( gasLimit ), + uint( gasUsed ), + uint( timestamp ), + bytes( extraData ), + + ... sealFields + ? sealFields.map( rlp.decode ) + : [ + bytes32( b.mixHash ), + bytes8( b.nonce ) + ] + ]) + ``` + + For POA-chains, the blockheader will use the `sealFields` (instead of mixHash and nonce) which are already RLP-encoded and should be added as raw data when using rlp.encode. + + ```js + if (keccak256(blockHeader) !== singedBlockHash) + throw new Error('Invalid Block') + ``` + + In case of the `eth_getBlockTransactionCountBy...`, the proof contains the full blockHeader already serilalized plus all transactionHashes. + This is needed in order to verify them in a merkle tree and compare them with the `transactionRoot`. + + + Requests requiring proof for blocks will return a proof of type `blockProof`. Depending on the request, the proof will contain the following properties: + + - `type` : constant : `blockProof` + - `signatures` : a array of signatures from the signers (if requested) of the requested block. + - `transactions`: a array of raw transactions of the block. This is only needed the last parameter of the request (includeTransactions) is `false`, In this case the result only contains the transactionHashes, but in order to verify we need to be able to build the complete merkle-trie, where the raw transactions are needed. If the complete transactions are included the raw transactions can be build from those values. + - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + - `uncles`: only if `fullProof` is requested we add all blockheaders of the uncles to the proof in order to verify the uncleRoot. + + + eth_getBlockByHash: + descr: | + Returns information about a block by hash. + + See [eth_getBlockByHash](https://eth.wiki/json-rpc/API#eth_getBlockByHash) for spec. + + params: + blockHash: + descr: the blockHash of the block + type: bytes32 + fullTx: + descr: if true the full transactions are contained in the result. + type: bool + returns: + descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. + alias: eth_getBlockByNumber + proof: + alias: eth_getBlockByNumber + example: + request: + - '0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585' + - false + response: + author: '0x0000000000000000000000000000000000000000' + difficulty: '0x2' + extraData: '0x696e667572612d696f0000000000000...31570f1e500' + gasLimit: '0x7a1200' + gasUsed: '0x20e145' + hash: '0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585' + logsBloom: '0x000008000000000000...00400100000000080' + miner: '0x0000000000000000000000000000000000000000' + number: '0x449956' + parentHash: '0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694' + receiptsRoot: '0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff' + sealFields: + - '0xa00000000000000000000000000000000000000000000000000000000000000000' + - '0x880000000000000000' + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347' + size: '0x74b' + stateRoot: '0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910' + timestamp: '0x605aec86' + totalDifficulty: '0x6564de' + transactions: + - '0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58' + - '0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641' + - '0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75' + - '0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d' + - '0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5' + - '0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8' + transactionsRoot: '0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc' + uncles: [] + in3: + proof: + type: blockProof + signatures: [] + transactions: + - '0xf8ac830331f78449504f80830186a094f74a...8a83ce8dc' + - '0xf8ac830331f88449504f80830186a094f74a...a81c2f1fee77' + - '0xf8a91e843b9aca008315a92594f0277caffea...c30d64dd139' + - '0xf8c601843b9aca008305573094309906d7b701...62f5e7a2319a' + - '0xf8c680843b9aca008305573094309906d7b701...78289116eac194e' + - '0xf9014b82020a843b9aca0083010f6894786f8d72...b649' + + + eth_getBlockTransactionCountByHash: + descr: returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByHash). + params: + blockHash: + descr: the blockHash of the block + type: bytes32 + proof: + alias: eth_getUncleCountByBlockNumber + returns: + descr: the number of transactions in the block + + eth_getBlockTransactionCountByNumber: + descr: returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByNumber). + params: + blockNumber: + descr: the blockNumber of the block + type: uint + proof: + alias: eth_getUncleCountByBlockNumber + returns: + descr: the number of transactions in the block + + eth_getUncleCountByBlockHash: + descr: returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). + params: + blockHash: + descr: the blockHash of the block + type: bytes32 + proof: + alias: eth_getUncleCountByBlockNumber + returns: + descr: the number of uncles + + eth_getUncleCountByBlockNumber: + descr: returns the number of uncles. For Spec, see [eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockNumber). + params: + blockNumber: + descr: the blockNumber of the block + type: uint + proof: + descr: | + Requests requiring proof for blocks will return a proof of type `blockProof`. Depending on the request, the proof will contain the following properties: + + - `type` : constant : `blockProof` + - `signatures` : a array of signatures from the signers (if requested) of the requested block. + - `block` : the serialized blockheader + - `transactions`: a array of raw transactions of the block. This is only needed if the number of transactions are requested. + - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + - `uncles`: a array of blockheaders of the uncles of the block. This is only needed if the number of uncles are requested. + returns: + descr: the number of uncles + + eth_getTransactionByBlockHashAndIndex: + descr: | + returns the transaction data. + + See JSON-RPC-Spec for [eth_getTransactionByBlockHashAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockHashAndIndex) for more details. + params: + blockHash: + descr: the blockhash containing the transaction. + type: bytes32 + index: + descr: the transactionIndex + type: uint + returns: + descr: the transactiondata or `null` if it does not exist + alias: eth_getTransactionByHash + proof: + alias: eth_getTransactionByHash + + example: + request: + - '0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee' + - '0xd5' + response: + blockHash: '0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee' + blockNumber: '0xb8a4a9' + from: '0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98' + gas: '0xac6b' + gasPrice: '0x1bf08eb000' + hash: '0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea' + input: '0x095ea7b300000000000000000000000...a7640000' + nonce: '0xa' + to: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce' + transactionIndex: '0xd5' + value: '0x0' + type: '0x0' + v: '0x25' + r: '0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4' + s: '0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78' + in3: + proof: + type: transactionProof + block: '0xf90212a033a7afd1b9...fa16cf2' + merkleProof: + - '0xf90131a0...91604f2f58080808080808080' + - '0xf851a06f...0808080808080808080' + - '0xf8d18080...8a2ac871c5808080' + - '0xf90111a05...0808080808080808080' + - '0xf8ae20b8...000a8ff46d2a2dd78' + txIndex: 213 + signatures: [] + + + eth_getTransactionByBlockNumberAndIndex: + descr: | + returns the transaction data. + + See JSON-RPC-Spec for [eth_getTransactionByBlockNumberAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockNumberAndIndex) for more details. + params: + blockNumber: + descr: the block number containing the transaction. + type: uint + index: + descr: the transactionIndex + type: uint + returns: + descr: the transactiondata or `null` if it does not exist + alias: eth_getTransactionByHash + proof: + alias: eth_getTransactionByHash + + example: + request: + - '0xb8a4a9' + - '0xd5' + response: + blockHash: '0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee' + blockNumber: '0xb8a4a9' + from: '0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98' + gas: '0xac6b' + gasPrice: '0x1bf08eb000' + hash: '0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea' + input: '0x095ea7b300000000000000000000000...a7640000' + nonce: '0xa' + to: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce' + transactionIndex: '0xd5' + value: '0x0' + type: '0x0' + v: '0x25' + r: '0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4' + s: '0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78' + in3: + proof: + type: transactionProof + block: '0xf90212a033a7afd1b9...fa16cf2' + merkleProof: + - '0xf90131a0...91604f2f58080808080808080' + - '0xf851a06f...0808080808080808080' + - '0xf8d18080...8a2ac871c5808080' + - '0xf90111a05...0808080808080808080' + - '0xf8ae20b8...000a8ff46d2a2dd78' + txIndex: 213 + signatures: [] + + + eth_getTransactionByHash: + descr: | + returns the transaction data. + + See JSON-RPC-Spec for [eth_getTransactionByHash](https://eth.wiki/json-rpc/API#eth_getTransactionByHash) for more details. + params: + txHash: + descr: the transactionHash of the transaction. + type: bytes32 + returns: + descr: the transactiondata or `null` if it does not exist + type: + to: + descr: receipient of the transaction. + type: address + from: + descr: sender or signer of the transaction + type: address + value: + descr: value in wei to send + type: uint + gas: + descr: the gas to be send along + type: uint + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + blockHash: + descr: blockHash of the block holding this transaction or `null` if still pending. + type: bytes32 + blockNumber: + descr: blockNumber of the block holding this transaction or `null` if still pending. + type: uint + hash: + descr: transactionHash + type: bytes32 + input: + descr: data of the transaaction + type: bytes + transactionIndex: + descr: index of the transaaction in the block + type: uint + v: + descr: recovery-byte of the signature + type: byte + r: + descr: x-value of the EC-Point of the signature + type: bytes32 + s: + descr: y-value of the EC-Point of the signature + type: bytes32 + + + example: + request: + - '0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b' + response: + blockHash: '0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee' + blockNumber: '0xb8a4a9' + from: '0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98' + gas: '0xac6b' + gasPrice: '0x1bf08eb000' + hash: '0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea' + input: '0x095ea7b300000000000000000000000...a7640000' + nonce: '0xa' + to: '0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce' + transactionIndex: '0xd5' + value: '0x0' + type: '0x0' + v: '0x25' + r: '0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4' + s: '0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78' + in3: + proof: + type: transactionProof + block: '0xf90212a033a7afd1b9...fa16cf2' + merkleProof: + - '0xf90131a0...91604f2f58080808080808080' + - '0xf851a06f...0808080808080808080' + - '0xf8d18080...8a2ac871c5808080' + - '0xf90111a05...0808080808080808080' + - '0xf8ae20b8...000a8ff46d2a2dd78' + txIndex: 213 + signatures: [] + + + proof: + descr: | + ```eval_rst + .. graphviz:: + + digraph minimal_nonplanar_graphs { + + fontname="Helvetica" + subgraph all { + + node [ fontsize = "12", style="", color=black fontname="Helvetica", shape=record ] + + subgraph block_header { + label="blockheader" style="" color=black + + bheader[ label="parentHash|...|transactionRoot|receiptRoot|stateRoot"] + troot:a -> bheader:tr + } + + subgraph cluster_client_registry { + label="Transaction Trie" color=lightblue style=filled + + troot[label="|0x123456|||||"] + ta[label="|0x123456||0xabcdef|||"] + tb[label="|0x98765||0xfcab34|||"] + tval[label="transaction data"] + + ta:a -> troot:a + tb:a -> troot:a + tval:a -> ta:a + } + + + } + } + + ``` + + In order to prove the transaction data, each transaction of the containing block must be serialized + + ```js + transaction = rlp.encode([ + uint( tx.nonce ), + uint( tx.gasPrice ), + uint( tx.gas || tx.gasLimit ), + address( tx.to ), + uint( tx.value ), + bytes( tx.input || tx.data ), + uint( tx.v ), + uint( tx.r ), + uint( tx.s ) + ]) + ``` + + and stored in a merkle tree with `rlp.encode(transactionIndex)` as key or path, since the blockheader only contains the `transactionRoot`, which is the root-hash of the resulting merkle tree. A merkle-proof with the transactionIndex of the target transaction will then be created from this tree. + + If the request requires proof (`verification`: `proof`) the node will provide an Transaction Proof as part of the in3-section of the response. + This proof section contains the following properties: + + - `type` : constant : `transactionProof` + - `block` : the serialized blockheader of the requested transaction. + - `signatures` : a array of signatures from the signers (if requested) of the above block. + - `txIndex` : The TransactionIndex as used in the MerkleProof ( not needed if the methode was `eth_getTransactionByBlock...`, since already given) + - `merkleProof`: the serialized nodes of the Transaction trie starting with the root node. + - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + + While there is no proof for a non existing transaction, if the request was a `eth_getTransactionByBlock...` the node must deliver a partial merkle-proof to verify that this node does not exist. + + + + eth_getLogs: + descr: searches for events matching the given criteria. See [eth_getLogs](https://eth.wiki/json-rpc/API#eth_getLogs) for the spec. + proof: + descr: | + Since logs or events are based on the TransactionReceipts, the only way to prove them is by proving the TransactionReceipt each event belongs to. + + That's why this proof needs to provide: + - all blockheaders where these events occured + - all TransactionReceipts plus their MerkleProof of the logs + - all MerkleProofs for the transactions in order to prove the transactionIndex + + The proof data structure will look like this: + + ```ts + Proof { + type: 'logProof', + logProof: { + [blockNr: string]: { // the blockNumber in hex as key + block : string // serialized blockheader + receipts: { + [txHash: string]: { // the transactionHash as key + txIndex: number // transactionIndex within the block + txProof: string[] // the merkle Proof-Array for the transaction + proof: string[] // the merkle Proof-Array for the receipts + } + } + } + } + } + ``` + + + In order to create the proof, we group all events into their blocks and transactions, so we only need to provide the blockheader once per block. + The merkle-proofs for receipts are created as described in the [Receipt Proof](#eth-gettransactionreceipt). + + + + + If the request requires proof (`verification`: `proof`) the node will provide an Transaction Proof as part of the in3-section of the response. + type: + type: + descr: proofType, which is `logProof` + type: string + logProof: + descr: The proof for all the receipts. This structure contains an object with the blockNumbers as keys. Each block contains the blockheader and the receipt proofs. + type: + block: + descr: serialized blockheader + type: bytes + receipts: + descr: array of proofs for the transayctionreceipts within the block + type: + txIndex: + descr: transactionIndex within the block + type: uint + txProof: + descr: the merkle Proof-Array for the transaction + type: bytes[] + proof: + descr: the merkle Proof-Array for the receipt + type: bytes[] + signatures: + descr: the array of signatures for all used blocks in the result. + type: signature[] + finalityBlocks: + descr: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + type: bytes[] + params: + filter: + descr: The filter criteria for the events. + type: + fromBlock: + descr: Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + type: uint | string + optional: true + default: latest + toBlock: + descr: Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + type: uint | string + optional: true + default: latest + address: + descr: Contract address or a list of addresses from which logs should originate. + type: address + optional: true + topics: + descr: Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. + type: bytes32[] + optional: true + blockhash: + descr: With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. + type: bytes32 + optional: true + + + eth_getBalance: + descr: gets the balance of an account for a given block + params: + account: + descr: address of the account + type: address + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint + returns: + descr: the balance + proof: + alias: eth_getStorageAt + example: + request: + - "0x2e333ec090f1028df0a3c39a918063443be82b2b" + - latest + response: '0x20599832af6ec00' + in3: + proof: + type: accountProof + block: '0xf90212a0af...5643f426d' + signatures: [] + accounts: + '0x2e333EC090f1028df0a3c39a918063443Be82B2b': + address: '0x2e333ec090f1028df0a3c39a918063443be82b2b' + accountProof: + - '0xf90211a099a5e...6d9f924480' + - '0xf90211a052b61...b19ff23445180' + - '0xf90211a0cc125...7e7afd9170280' + - '0xf90211a088c91...555f0b76fc6ec80' + - '0xf90211a0641a3...477d355d557a180' + - '0xf90211a0619e5...5977318c9487280' + - '0xf90111a0e25a1...641683d34adae808080' + - '0xf86e9d3f681a18...2273b7bfad8045d85a470' + balance: '0x20599832af6ec00' + codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + nonce: '0x5' + storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' + storageProof: [] + + + + eth_getTransactionCount: + descr: gets the nonce or number of transaction sent from this account at a given block + params: + account: + descr: address of the account + type: address + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint + returns: + descr: the nonce + proof: + alias: eth_getStorageAt + example: + request: + - "0x2e333ec090f1028df0a3c39a918063443be82b2b" + - latest + response: '0x5' + in3: + proof: + type: accountProof + block: '0xf90212a0af...5643f426d' + signatures: [] + accounts: + '0x2e333EC090f1028df0a3c39a918063443Be82B2b': + address: '0x2e333ec090f1028df0a3c39a918063443be82b2b' + accountProof: + - '0xf90211a099a5e...6d9f924480' + - '0xf90211a052b61...b19ff23445180' + - '0xf90211a0cc125...7e7afd9170280' + - '0xf90211a088c91...555f0b76fc6ec80' + - '0xf90211a0641a3...477d355d557a180' + - '0xf90211a0619e5...5977318c9487280' + - '0xf90111a0e25a1...641683d34adae808080' + - '0xf86e9d3f681a18...2273b7bfad8045d85a470' + balance: '0x20599832af6ec00' + codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + nonce: '0x5' + storageHash: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' + storageProof: [] + + + + + eth_getCode: + descr: gets the code of a given contract + params: + account: + descr: address of the account + type: address + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint + returns: + descr: the code as hex + proof: + alias: eth_getStorageAt + example: + request: + - "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f" + - latest + response: '0x6080604052348...6c634300050a0040' + in3: + proof: + type: accountProof + block: '0xf9020da02776...8ba1d5458be3b98' + signatures: [] + accounts: + '0xaC1b824795E1EB1F6e609FE0dA9b9af8bEaAb60F': + address: '0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f' + accountProof: + - '0xf90211a03...c41e862bd80' + - '0xf90211a02...c5766ac3ec9180' + - '0xf90211a0f...cdad27ecdfbc1c4c66e680' + - '0xf90211a08...84621739c3777ea1d5080' + - '0xf90211a00...02388c08615b82ef0320614380' + - '0xf90211a03...1b16a8c050f61d80' + - '0xf8f18080a...cafe05823be8080' + - '0xf8669d3ad8...903305697a1' + balance: '0x0' + codeHash: '0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1' + nonce: '0x1' + storageHash: '0x4d6c5972bcc0c8229c8b041df4aa70879e37e9f7eb47530e4232b317438524ed' + storageProof: [] + + + + eth_getStorageAt: + descr: gets the storage value of a given key + params: + account: + descr: address of the account + type: address + key: + descr: key to look for + type: bytes32 + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint + returns: + descr: the value of the storage slot. + proof: + type: + type: + descr: proof type, which is `accountProof` + type: string + block: + descr: serialized blockheader + type: bytes + accounts: + descr: object with all required accounts (using the address as keys) + type: + address: + descr: address of the account + type: address + balance: + descr: the balance + type: uint + nonce: + descr: nonce of the account + type: uint + codeHash: + descr: codehash of the account + type: bytes32 + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + type: bytes[] + storageProof: + descr: Array of Proofs for all required storage values + type: + key: + descr: the storage key (or hash) + type: uint + value: + descr: the storage value + type: bytes32 + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes[] + + signatures: + descr: the array of signatures for all used blocks in the result. + type: signature[] + finalityBlocks: + descr: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + type: bytes[] + + descr: | + Each of these account values are stored in the account-object: + + ```js + account = rlp.encode([ + uint( nonce), + uint( balance), + bytes32( storageHash || ethUtil.KECCAK256_RLP), + bytes32( codeHash || ethUtil.KECCAK256_NULL) + ]) + ``` + + The proof of an account is created by taking the state merkle tree and creating a MerkleProof. Since all of the above RPC-methods only provide a single value, the proof must contain all four values in order to encode them and verify the value of the MerkleProof. + + For verification, the `stateRoot` of the blockHeader is used and `keccak(accountProof.address)` as the path or key within the merkle tree. + + ```js + verifyMerkleProof( + block.stateRoot, // expected merkle root + keccak(accountProof.address), // path, which is the hashed address + accountProof.accountProof), // array of Buffer with the merkle-proof-data + isNotExistend(accountProof) ? null : serializeAccount(accountProof), // the expected serialized account + ) + ``` + + In case the account does not exist yet (which is the case if `none` == `startNonce` and `codeHash` == `'0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'`), the proof may end with one of these nodes: + + - The last node is a branch, where the child of the next step does not exist. + - The last node is a leaf with a different relative key. + + Both would prove that this key does not exist. + + For `eth_getStorageAt`, an additional storage proof is required. This is created by using the `storageHash` of the account and creating a MerkleProof using the hash of the storage key (`keccak(key)`) as path. + + + ```js + verifyMerkleProof( + bytes32( accountProof.storageHash ), // the storageRoot of the account + keccak(bytes32(s.key)), // the path, which is the hash of the key + s.proof.map(bytes), // array of Buffer with the merkle-proof-data + s.value === '0x0' ? null : util.rlp.encode(s.value) // the expected value or none to proof non-existence + )) + ``` + + + ```eval_rst + .. graphviz:: + + digraph minimal_nonplanar_graphs { + + fontname="Helvetica" + subgraph all { + + node [ fontsize = "12", style="", color=black fontname="Helvetica", shape=record ] + + subgraph cluster_block_header { + label="Blockheader" color=white style=filled + + bheader[ label="parentHash|...|stateRoot|transactionRoot|receiptRoot|..."] + } + + subgraph cluster_state_trie { + label="State Trie" color=lightblue style=filled + + troot[label="|0x123456|||||0xabcdef"] + ta[label="|0x123456||0xabcdef|||"] + tb[label="|0x98765||0xfcab34|||"] + tval[label="nonce|balance|storageHash|codeHash"] + + ta:a -> troot:a + tb:a -> troot:b + tval:a -> ta:a + } + + subgraph cluster_storage_trie { + label="Storage Trie" color=lightblue style=filled + + sroot[label="|0x123456|||||0xabcdef"] + sa[label="|0x123456||0xabcdef|||"] + sb[label="|0x98765||0xfcab34|||"] + sval[label="storage value"] + + sa:a -> sroot:a + sb:a -> sroot:b + sval:a -> sa:a + } + + sroot:a -> tval:sr + troot:a -> bheader:tr + + } + } + + ``` + + + + + If the request requires proof (`verification`: `proof`) the node will provide an Account Proof as part of the in3-section of the response. + + example: + request: + - "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f" + - "0x0" + - latest + response: '0x19' + in3: + proof: + type: accountProof + block: '0xf90218a0e625bee...87a38707dbbc' + signatures: [] + accounts: + '0xaC1b824795E1EB1F6e609FE0dA9b9af8bEaAb60F': + address: '0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f' + accountProof: + - '0xf90211a0cef18...56e5cfcf3ef70de80' + - '0xf90211a0b67e01...2a13db20dcf291d533480' + - '0xf90211a05df65...be23ffb94580' + - '0xf90211a0825413...75d61184621739c3777ea1d5080' + - '0xf90211a000a403...82ef0320614380' + - '0xf90211a03b0114...a6e41b16a8c050f61d80' + - '0xf8f18080a01a27...96fcdfe84cafe05823be8080' + - '0xf8669d3ad8a871b...d82903305697a1' + balance: '0x0' + codeHash: '0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1' + nonce: '0x1' + storageHash: '0x4d6c5972bcc0c8229c8b041df4aa70879e37e9f7eb47530e4232b317438524ed' + storageProof: + - key: '0x0' + value: '0x19' + proof: + - '0xf90211a084b9482...1ad85a4f2f1680' + - '0xf901b1a0625f8d3...6e0788855d2780' + - '0xf851a08a14eff77...08080808080808080' + - '0xe19f3decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56319' + diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml new file mode 100644 index 000000000..4c0a89682 --- /dev/null +++ b/c/src/verifier/eth1/full/rpc.yml @@ -0,0 +1,246 @@ +eth: + + eth_estimateGas: + descr: calculates the gas needed to execute a transaction. for spec see [eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimateGas) + params: + tx: + descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + type: + to: + descr: address of the contract + type: address + from: + descr: sender of the address + type: address + optional: true + value: + descr: value in wei to send + type: uint + optional: true + gas: + descr: the gas to be send along + type: uint + optional: true + default: 21000 + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + optional: true + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + optional: true + data: + descr: the data-section of the transaction, which includes the functionhash and the abi-encoded arguments + type: bytes + optional: true + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint | string + + returns: + descr: the amount of gass needed. + proof: + alias: eth_call + + + eth_call: + descr: calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) + params: + tx: + descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + type: + to: + descr: address of the contract + type: address + from: + descr: sender of the address + type: address + optional: true + value: + descr: value in wei to send + type: uint + optional: true + gas: + descr: the gas to be send along + type: uint + optional: true + default: 21000 + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + optional: true + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + optional: true + data: + descr: the data-section of the transaction, which includes the functionhash and the abi-encoded arguments + type: bytes + optional: true + block: + descr: the blockNumber or one of `latest`, `earliest`or `pending` + type: uint | string + + returns: + descr: the abi-encoded result of the function. + + example: + request: + - to: "0x2736D225f85740f42D17987100dc8d58e9e16252" + data: "0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001" + - latest + response: 0x0000000000000000000000000... + in3: + proof: + type: callProof + block: 0xf90215a0c... + signatures: + - "..." + accounts: + '0x2736D225f85740f42D17987100dc8d58e9e16252': + accountProof: + - 0xf90211a095... + - 0xf90211a010... + - 0xf90211a062... + - 0xf90211a091... + - 0xf90211a03a... + - 0xf901f1a0d1... + - 0xf8b18080808... + address: '0x2736d225f85740f42d17987100dc8d58e9e16252' + balance: '0x4fffb' + codeHash: '0x2b8bdc59ce78fd8c248da7b5f82709e04f2149c39e899c4cdf4587063da8dc69' + nonce: '0x1' + storageHash: '0xbf904e79d4ebf851b2380d81aab081334d79e231295ae1b87f2dd600558f126e' + storageProof: + - key: '0x0' + proof: + - 0xf901f1a0db74... + - 0xf87180808080... + - 0xe2a0200decd9....05 + value: '0x5' + - key: '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e569' + proof: + - 0xf901f1a0db74... + - 0xf891a0795a99... + - 0xe2a020ab8540...43 + value: '0x43' + - key: '0xaaab8540682e3a537d17674663ea013e92c83fdd69958f314b4521edb3b76f1a' + proof: + - 0xf901f1a0db747... + - 0xf891808080808... + - 0xf843a0207bd5ee... + value: '0x68747470733a2f2f696e332e736c6f636b2e69742f6d61696e6e65742f6e642d' + proof: + type: + type: + descr: proof type, which is `callProof` + type: string + block: + descr: serialized blockheader + type: bytes + accounts: + descr: Object with the addresses of all accounts required to run the call as keys. This includes also all storage values (SLOAD) including proof used. The DataStructure of the Proof for each account is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof). + type: + address: + descr: address of the account + type: address + balance: + descr: the balance + type: uint + nonce: + descr: nonce of the account + type: uint + codeHash: + descr: codehash of the account + type: bytes32 + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + type: bytes[] + storageProof: + descr: Array of Proofs for all required storage values + type: + key: + descr: the storage key (or hash) + type: uint + value: + descr: the storage value + type: bytes32 + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes[] + + signatures: + descr: the array of signatures for all used blocks in the result. + type: signature[] + finalityBlocks: + descr: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + type: bytes[] + + descr: | + Verifying the result of an `eth_call` is a little bit more complex because the response is a result of executing opcodes in the vm. The only way to do so is to reproduce it and execute the same code. That's why a call proof needs to provide all data used within the call. This means: + + - All referred accounts including the code (if it is a contract), storageHash, nonce and balance. + - All storage keys that are used (this can be found by tracing the transaction and collecting data based on the `SLOAD`-opcode). + - All blockdata, which are referred at (besides the current one, also the `BLOCKHASH`-opcodes are referring to former blocks). + + For verifying, you need to follow these steps: + + 1. Serialize all used blockheaders and compare the blockhash with the signed hashes. (See [BlockProof](#blockproof)) + + 2. Verify all used accounts and their storage as showed in [Account Proof](#account-proof). + + 3. Create a new [VM](https://github.com/ethereumjs/ethereumjs-vm) with a MerkleTree as state and fill in all used value in the state: + + + ```js + // create new state for a vm + const state = new Trie() + const vm = new VM({ state }) + + // fill in values + for (const adr of Object.keys(accounts)) { + const ac = accounts[adr] + + // create an account-object + const account = new Account([ac.nonce, ac.balance, ac.stateRoot, ac.codeHash]) + + // if we have a code, we will set the code + if (ac.code) account.setCode( state, bytes( ac.code )) + + // set all storage-values + for (const s of ac.storageProof) + account.setStorage( state, bytes32( s.key ), rlp.encode( bytes32( s.value ))) + + // set the account data + state.put( address( adr ), account.serialize()) + } + + // add listener on each step to make sure it uses only values found in the proof + vm.on('step', ev => { + if (ev.opcode.name === 'SLOAD') { + const contract = toHex( ev.address ) // address of the current code + const storageKey = bytes32( ev.stack[ev.stack.length - 1] ) // last element on the stack is the key + if (!getStorageValue(contract, storageKey)) + throw new Error(`incomplete data: missing key ${storageKey}`) + } + /// ... check other opcodes as well + }) + + // create a transaction + const tx = new Transaction(txData) + + // run it + const result = await vm.runTx({ tx, block: new Block([block, [], []]) }) + + // use the return value + return result.vm.return + ``` + + In the future, we will be using the same approach to verify calls with ewasm. + + If the request requires proof (`verification`: `proof`) the node will provide an Call Proof as part of the in3-section of the response. Details on how create the proof can be found in the [CallProof-Chapter](#call-proof). + diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml index 3d6cc2f85..79e146c51 100644 --- a/c/src/verifier/eth1/nano/rpc.yml +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -26,3 +26,191 @@ eth: * **txIndex** `integer` - The transactionIndex within the block (for transaactions and receipts). * **signatures** `Signature[]` - Requested signatures. + eth_getTransactionReceipt: + descr: The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). + params: + txHash: + descr: the transactionHash + type: bytes32 + returns: + descr: the TransactionReceipt or `null` if it does not exist. + type: + blockNumber: + descr: the blockNumber + type: uint + blockHash: + descr: blockhash if ther containing block + type: bytes32 + contractAddress: + descr: the deployed contract in case the tx did deploy a new contract + type: address + cumulativeGasUsed: + descr: gas used for all transaction up to this one in the block + type: uint + gasUsed: + descr: gas used by this transaction. + type: uint + logs: + descr: array of events created during execution of the tx + type: + address: + descr: the address triggering the event. + type: address + blockNumber: + descr: the blockNumber + type: uint + blockHash: + descr: blockhash if ther containing block + type: bytes32 + data: + descr: abi-encoded data of the event (all non indexed fields) + type: bytes + logIndex: + descr: the index of the even within the block. + type: uint + removed: + descr: the reorg-status of the event. + type: bool + topics: + descr: array of 32byte-topics of the indexed fields. + type: bytes32[] + transactionHash: + descr: requested transactionHash + type: bytes32 + transactionIndex: + descr: transactionIndex within the containing block. + type: uint + transactionLogIndex: + descr: index of the event within the transaction. + type: uint + type: + descr: mining-status + type: string + logsBloom: + descr: bloomfilter used to detect events for `eth_getLogs` + type: bytes128 + status: + descr: error-status of the tx. 0x1 = success 0x0 = failure + type: uint + transactionHash: + descr: requested transactionHash + type: bytes32 + transactionIndex: + descr: transactionIndex within the containing block. + type: uint + + example: + request: + - '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + response: + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + contractAddress: + cumulativeGasUsed: '0x2466d' + gasUsed: '0x2466d' + logs: + - address: '0x85ec283a3ed4b66df4da23656d4bf8a507383bca' + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + data: 0x00000000000... + logIndex: '0x0' + removed: false + topics: + - '0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8' + - '0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6' + - '0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + transactionLogIndex: '0x0' + type: mined + logsBloom: 0x00000000000000000000200000... + root: + status: '0x1' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + in3: + proof: + type: receiptProof + block: 0xf9023fa019e9d929ab... + txProof: + - 0xf851a083c8446ab932130... + merkleProof: + - 0xf851a0b0f5b7429a54b10... + txIndex: 0 + signatures: + - "..." + merkleProofPrev: + - 0xf851a0b0f5b7429a54b10... + + proof: + descr: | + ```eval_rst + .. graphviz:: + + digraph minimal_nonplanar_graphs { + + fontname="Helvetica" + subgraph all { + + node [ fontsize = "12", style="", color=black fontname="Helvetica", shape=record ] + + subgraph blockheader { + label="blocheader" style="" color=black + + bheader[ label="parentHash|...|transactionRoot|receiptRoot|stateRoot"] + troot:a -> bheader:tr + } + + subgraph cluster_client_registry { + label="Receipt Trie" color=lightblue style=filled + + troot[label="|0x123456|||||"] + ta[label="|0x123456||0xabcdef|||"] + tb[label="|0x98765||0xfcab34|||"] + tval[label="transaction receipt"] + + ta:a -> troot:a + tb:a -> troot:a + tval:a -> ta:a + } + + + } + } + + ``` + + The proof works similiar to the transaction proof. + + In order to create the proof we need to serialize all transaction receipts + + ```js + transactionReceipt = rlp.encode([ + uint( r.status || r.root ), + uint( r.cumulativeGasUsed ), + bytes256( r.logsBloom ), + r.logs.map(l => [ + address( l.address ), + l.topics.map( bytes32 ), + bytes( l.data ) + ]) + ].slice(r.status === null && r.root === null ? 1 : 0)) + ``` + + and store them in a merkle tree with `rlp.encode(transactionIndex)` as key or path, since the blockheader only contains the `receiptRoot`, which is the root-hash of the resulting merkle tree. A merkle proof with the transactionIndex of the target transaction receipt will then be created from this tree. + + Since the merkle proof is only proving the value for the given transactionIndex, we also need to prove that the transactionIndex matches the transactionHash requested. This is done by adding another MerkleProof for the transaction itself as described in the [Transaction Proof](#eth-gettransactionbyhash). + + + If the request requires proof (`verification`: `proof`) the node will provide an Transaction Proof as part of the in3-section of the response. + This proof section contains the following properties: + + - `type` : constant : `receiptProof` + - `block` : the serialized blockheader of the requested transaction. + - `signatures` : a array of signatures from the signers (if requested) of the above block. + - `txIndex` : The TransactionIndex as used in the MerkleProof + - `txProof` : the serialized nodes of the Transaction trie starting with the root node. This is needed in order to proof that the required transactionHash matches the receipt. + - `merkleProof`: the serialized nodes of the Transaction Receipt trie starting with the root node. + - `merkleProofPrev`: the serialized nodes of the previous Transaction Receipt (if txInxdex>0) trie starting with the root node. This is only needed if full-verification is requested. With a verified previous Receipt we can proof the `usedGas`. + - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. + diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 00958721e..9fccfbe3b 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -3,6 +3,8 @@ const fs = require('fs') const docs = {} let config = {} +const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) +const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { @@ -46,17 +48,19 @@ for (const s of Object.keys(docs).sort()) { if (rpcs.descr) console.log(rpcs.descr + '\n') delete rpcs.descr for (const rpc of Object.keys(rpcs).sort()) { - console.log('### ' + rpc + '\n\n') const def = rpcs[rpc] + console.log('### ' + rpc + '\n\n') + asArray(def.alias).forEach(_ => console.log(rpc + ' is just an alias for ' + link(_) + '.See Details there.\n\n')) if (def.descr) console.log(def.descr + '\n') if (def.params) { - console.log("Parameters:\n") + console.log("*Parameters:*\n") let i = 1 for (const par of Object.keys(def.params)) { const p = def.params[par] - let s = (i++) + '. `' + par + '`' - if (p.type) s += ':' + (typeof p.type === 'string' ? p.type : 'object') + let s = (i++) + '. **' + par + '**' + if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' if (p.descr) s += ' - ' + p.descr + if (p.alias) s += ' The data structure of ' + par + ' is the same as ' + link(def.returns.alias) + '. See Details there.' console.log(s) if (typeof p.type === 'object') { console.log('\nThe ' + par + ' params support the following properties :\n') @@ -66,23 +70,28 @@ for (const s of Object.keys(docs).sort()) { } console.log() } - else - console.log("Parameters: - \n") + else if (!def.alias) + console.log("*Parameters:* - \n") if (def.returns) { if (def.returns.type) { - console.log('Returns: ' + (typeof def.returns.type === 'string' ? def.returns.type : 'object') + '\n\n' + def.returns.descr + '\n') + console.log('*Returns:* ' + (typeof def.returns.type === 'string' ? def.returns.type : 'object') + '\n\n' + def.returns.descr + '\n') if (typeof def.returns.type === 'object') { console.log('\nThe return value contains the following properties :\n') print_object(def.returns.type, '') } } + else if (def.returns.alias) + console.log('*Returns:*\n\nThe Result of `' + rpc + '` is the same as ' + link(def.returns.alias) + '. See Details there.\n') else - console.log('Returns:\n\n' + def.returns.descr + '\n') + console.log('*Returns:*\n\n' + (def.returns.descr || '') + '\n') } if (def.proof) { - console.log('Proof:\n\n' + def.proof.descr + '\n') + console.log('*Proof:*\n\n' + (def.proof.descr || '') + '\n') + if (def.proof.alias) + console.log('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') + if (def.proof.type) { console.log("This proof section contains the following properties:\n\n") print_object(def.proof.type, '') @@ -92,18 +101,20 @@ for (const s of Object.keys(docs).sort()) { - if (def.example && def.example.request) { - console.log('Request:\n') - console.log('```js\n' + JSON.stringify({ method: rpc, params: def.example.request }, null, 2)) + asArray(def.example).forEach(ex => { + const req = { method: rpc, params: ex.request || [] } + if (def.proof) req.in3 = { "verification": "proof" } + console.log('*Request:*\n') + console.log('```js\n' + JSON.stringify(req, null, 2)) console.log('```\n') - } - if (def.example && def.example.response) { - const data = { result: def.example.response } - if (def.example.in3) data.in3 = def.example.in3 - console.log('Response:\n') - console.log('```js\n' + JSON.stringify(data, null, 2)) - console.log('```\n') - } + if (ex.response) { + const data = { result: ex.response } + if (ex.in3) data.in3 = ex.in3 + console.log('*Response:*\n') + console.log('```js\n' + JSON.stringify(data, null, 2)) + console.log('```\n') + } + }) } } From 38cd80529fbc9f51280886595287047bd7316a69 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 14:20:46 +0100 Subject: [PATCH 024/221] support for eth_signTransaction --- c/src/api/eth1/rpc_api.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 67fbc4dcb..a1e1324a4 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -547,15 +547,29 @@ static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { - bytes_t* data = d_get_bytes_at(ctx->params, 0); - bytes_t* from_b = d_get_bytes_at(ctx->params, 1); + CHECK_PARAMS_LEN(ctx->req, ctx->parmas, 1) + d_token_t* tx_data = ctx->params + 1; + bytes_t tx_raw = bytes(NULL, 0); + bytes_t* from_b = NULL; + bytes_t* data = NULL; + if (strcmp(ctx->method,"eth_signTransaction")==0 || d_type(tx_data)==T_OBJECT { + TRY(eth_prepare_unsigned_tx(tx_data,ctx->req,&tx_raw))) + from_b = d_get_bytes(tx_data,K_FROM); + data = &tx_raw; + } + else { + data = d_get_bytes_at(ctx->params, 0); + from_b = d_get_bytes_at(ctx->params, 1); + } + address_t from; memset(from, 0, 20); if (from_b && from_b->data && from_b->len == 20) memcpy(from, from_b->data, 20); bytes_t dst = {0}; #if defined(ETH_BASIC) || defined(ETH_FULL) - TRY(eth_sign_raw_tx(*data, ctx->req, from, &dst)) + TRY_FINAL(eth_sign_raw_tx(*data, ctx->req, from, &dst), _free(tx_raw.data)) #else + _free(tx_raw.data); if (data || ctx || from[0] || ctx->params) return req_set_error(ctx->req, "eth_basic is needed in order to use eth_signTx", IN3_EINVAL); #endif in3_rpc_handle_with_bytes(ctx, dst); @@ -573,6 +587,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("sha256", in3_sha256(ctx)) TRY_RPC("web3_clientVersion", web3_clientVersion(ctx)) TRY_RPC("eth_sign", in3_sign_data(ctx)) + TRY_RPC("eth_signTransaction", in3_signTx(ctx)) if (strncmp(ctx->method, "in3_", 4)) return IN3_EIGNORE; // shortcut From 91059390827e7c19197a2b3dd37722ed04390084 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 16:18:32 +0100 Subject: [PATCH 025/221] added transaction as type --- c/src/api/eth1/rpc.yml | 81 +++++++++++++++++++++++++-------------- scripts/build_rpc_docu.js | 26 +++++++++---- 2 files changed, 71 insertions(+), 36 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index d82368dcf..152bbd13c 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -1,3 +1,35 @@ +types: + transaction: + to: + descr: receipient of the transaction. + type: address + from: + descr: sender of the address (if not sepcified, the first signer will be the sender) + type: address + value: + descr: value in wei to send + type: uint + optional: true + gas: + descr: the gas to be send along + type: uint + optional: true + default: 21000 + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + optional: true + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + optional: true + data: + descr: the data-section of the transaction + type: bytes + optional: true + + + in3: in3_abiEncode: @@ -190,34 +222,7 @@ in3: params: tx: descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - type: - to: - descr: receipient of the transaction. - type: address - from: - descr: sender of the address (if not sepcified, the first signer will be the sender) - type: address - value: - descr: value in wei to send - type: uint - optional: true - gas: - descr: the gas to be send along - type: uint - optional: true - default: 21000 - gasPrice: - descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint - optional: true - nonce: - descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint - optional: true - data: - descr: the data-section of the transaction - type: bytes - optional: true + type: transaction returns: descr: the unsigned raw transaction as hex. @@ -414,3 +419,23 @@ eth: response: '0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b' + + eth_signTransaction: + descr: Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. + params: + tx: + descr: transaction to sign + type: transaction + returns: + descr: the raw signed transaction + example: + request: + - data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155" + gas: "0x76c0" + gasPrice: "0x9184e72a000" + to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567" + value: "0x9184e72a" + response: '0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b' + + diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 9fccfbe3b..5902114a4 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -3,12 +3,18 @@ const fs = require('fs') const docs = {} let config = {} +let types = {} const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' +const getType = val => typeof val === 'object' ? val : (types['' + val] || val) function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { const ob = yaml.parse(fs.readFileSync(dir + '/' + f.name, 'utf-8')) + if (ob.types) { + types = { ...types, ...ob.types } + delete ob.types + } for (const k of Object.keys(ob)) { if (ob[k].config) config = { ...config, ...ob[k].config } delete ob[k].config @@ -22,14 +28,15 @@ function print_object(def, pad) { for (const prop of Object.keys(def)) { let s = pad + '* **' + prop + '**' const p = def[prop] + const pt = getType(p.type) if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' if (p.optional) s += ' *(optional)*' if (p.descr) s += ' - ' + p.descr if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' console.log(s) - if (typeof p.type === 'object') { + if (typeof pt === 'object') { console.log('The ' + prop + ' object supports the following properties :\n' + pad) - print_object(p.type, pad + ' ') + print_object(pt, pad + ' ') } if (p.example) console.log('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) @@ -57,14 +64,15 @@ for (const s of Object.keys(docs).sort()) { let i = 1 for (const par of Object.keys(def.params)) { const p = def.params[par] + const pt = getType(p.type) let s = (i++) + '. **' + par + '**' if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' if (p.descr) s += ' - ' + p.descr if (p.alias) s += ' The data structure of ' + par + ' is the same as ' + link(def.returns.alias) + '. See Details there.' console.log(s) - if (typeof p.type === 'object') { + if (typeof pt === 'object') { console.log('\nThe ' + par + ' params support the following properties :\n') - print_object(p.type, '') + print_object(pt, '') } } @@ -76,9 +84,10 @@ for (const s of Object.keys(docs).sort()) { if (def.returns) { if (def.returns.type) { console.log('*Returns:* ' + (typeof def.returns.type === 'string' ? def.returns.type : 'object') + '\n\n' + def.returns.descr + '\n') - if (typeof def.returns.type === 'object') { + const pt = getType(def.returns.type) + if (typeof pt === 'object') { console.log('\nThe return value contains the following properties :\n') - print_object(def.returns.type, '') + print_object(pt, '') } } else if (def.returns.alias) @@ -89,12 +98,13 @@ for (const s of Object.keys(docs).sort()) { if (def.proof) { console.log('*Proof:*\n\n' + (def.proof.descr || '') + '\n') + const pt = getType(def.proof.type) if (def.proof.alias) console.log('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') - if (def.proof.type) { + if (pt) { console.log("This proof section contains the following properties:\n\n") - print_object(def.proof.type, '') + print_object(pt, '') console.log("\n\n") } } From 59cbaefbf7e3fa90054e3b68c05f42323b02cddf Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 24 Mar 2021 21:44:43 +0100 Subject: [PATCH 026/221] more rpc-docu --- c/src/verifier/btc/rpc.yml | 94 +++++++++++ c/src/verifier/eth1/basic/rpc.yml | 255 +++++++++++++++++------------- c/src/verifier/eth1/full/rpc.yml | 30 +--- c/src/verifier/eth1/nano/rpc.yml | 131 +++++++-------- c/src/verifier/ipfs/rpc.yml | 45 ++++++ 5 files changed, 353 insertions(+), 202 deletions(-) create mode 100644 c/src/verifier/ipfs/rpc.yml diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 59aa70545..fa81d050f 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -34,3 +34,97 @@ btc: default: 10 optional: true + + getblockheader: + descr: Returns data of block header for given block hash. The returned level of details depends on the argument verbosity. + params: + hash: + descr: The block hash + type: bytes32 + verbosity: + descr: 0 or false for the hex-encoded data, 1 or true for a json object + type: uint + in3Params: + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + returns: + descr: | + the blockheader. + - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + - verbose `1` or `true`: an object representing the blockheader. + type: + hash: + descr: the block hash (same as provided) + type: bytes32 + confirmations: + descr: The number of confirmations, or -1 if the block is not on the main chain + type: int + height: + descr: The block height or index + type: uint + version: + descr: The block version + type: uint + versionHex: + descr: The block version formatted in hexadecimal + type: hex + merkleroot: + descr: The merkle root ( 32 bytes ) + type: bytes32 + time: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + mediantime: + descr: The median block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + nonce: + descr: The nonce + type: uint + bits: + descr: The bits ( 4 bytes as hex) representing the target + type: bytes4 + difficulty: + descr: The difficulty + type: uint + chainwork: + descr: Expected number of hashes required to produce the current chain (in hex) + type: uint + nTx: + descr: The number of transactions in the block. + type: uint + previousblockhash: + descr: The hash of the previous block + type: bytes32 + nextblockhash: + descr: The hash of the next block + type: bytes32 + + example: + request: + - "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220" + - true + response: + hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + confirmations: 8268 + height: 624958 + version: 536928256 + versionHex: 2000e000 + merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb + time: 1586333924 + mediantime: 1586332639 + nonce: 1985217615 + bits: 17143b41 + difficulty: 13912524048945.91 + chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 + nTx: 33 + previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 + nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 + in3: + proof: + final: 0x00e0ff2720723034053c305058beb92ed010...276470 + cbtx: 0x0100000000010100000000000000000000000...39da2fc + cbtxMerkleProof: 0x6a8077bb4ce76b71d7742ddd368770279a64667b...52e688 diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 0d3cd7639..07bbbee89 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -1,6 +1,108 @@ -eth: - +types: + blockdata: + number: + descr: the block number. `null` when its pending block. + type: uint + hash: + descr: hash of the block. `null` when its pending block. + type: bytes32 + parentHash: + descr: hash of the parent block. + type: bytes32 + nonce: + descr: hash of the generated proof-of-work. `null` when its pending block. + type: uint64 + sha3Uncles: + descr: SHA3 of the uncles Merkle root in the block. + type: bytes32 + logsBloom: + descr: the bloom filter for the logs of the block. `null` when its pending block. + type: bytes256 + transactionsRoot: + descr: the root of the transaction trie of the block. + type: bytes32 + stateRoot: + descr: the root of the final state trie of the block. + type: bytes32 + receiptsRoot: + descr: the root of the receipts trie of the block. + type: bytes32 + miner: + descr: the address of the beneficiary to whom the mining rewards were given. + type: address + difficulty: + descr: integer of the difficulty for this block. + type: uint + totalDifficulty: + descr: integer of the total difficulty of the chain until this block. + type: uint + extraData: + descr: the "extra data" field of this block. + type: bytes + size: + descr: integer the size of this block in bytes. + type: uint + gasLimit: + descr: the maximum gas allowed in this block. + type: uint + gasUsed: + descr: the total used gas by all transactions in this block. + type: uint + timestamp: + descr: the unix timestamp for when the block was collated. + type: uint + transactions: + descr: Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. + type: transaction[] + uncles: + descr: Array of uncle hashes. + type: bytes32[] + + transactiondata: + to: + descr: receipient of the transaction. + type: address + from: + descr: sender or signer of the transaction + type: address + value: + descr: value in wei to send + type: uint + gas: + descr: the gas to be send along + type: uint + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint + blockHash: + descr: blockHash of the block holding this transaction or `null` if still pending. + type: bytes32 + blockNumber: + descr: blockNumber of the block holding this transaction or `null` if still pending. + type: uint + hash: + descr: transactionHash + type: bytes32 + input: + descr: data of the transaaction + type: bytes + transactionIndex: + descr: index of the transaaction in the block + type: uint + v: + descr: recovery-byte of the signature + type: byte + r: + descr: x-value of the EC-Point of the signature + type: bytes32 + s: + descr: y-value of the EC-Point of the signature + type: bytes32 +eth: eth_blockNumber: descr: | @@ -29,64 +131,8 @@ eth: type: bool result: descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. - type: - number: - descr: the block number. `null` when its pending block. - type: uint - hash: - descr: hash of the block. `null` when its pending block. - type: bytes32 - parentHash: - descr: hash of the parent block. - type: bytes32 - nonce: - descr: hash of the generated proof-of-work. `null` when its pending block. - type: uint64 - sha3Uncles: - descr: SHA3 of the uncles Merkle root in the block. - type: bytes32 - logsBloom: - descr: the bloom filter for the logs of the block. `null` when its pending block. - type: bytes256 - transactionsRoot: - descr: the root of the transaction trie of the block. - type: bytes32 - stateRoot: - descr: the root of the final state trie of the block. - type: bytes32 - receiptsRoot: - descr: the root of the receipts trie of the block. - type: bytes32 - miner: - descr: the address of the beneficiary to whom the mining rewards were given. - type: address - difficulty: - descr: integer of the difficulty for this block. - type: uint - totalDifficulty: - descr: integer of the total difficulty of the chain until this block. - type: uint - extraData: - descr: the "extra data" field of this block. - type: bytes - size: - descr: integer the size of this block in bytes. - type: uint - gasLimit: - descr: the maximum gas allowed in this block. - type: uint - gasUsed: - descr: the total used gas by all transactions in this block. - type: uint - timestamp: - descr: the unix timestamp for when the block was collated. - type: uint - transactions: - descr: Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. - type: transaction[] - uncles: - descr: Array of uncle hashes. - type: bytes32[] + type: blockdata + example: request: @@ -202,7 +248,8 @@ eth: type: bool returns: descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. - alias: eth_getBlockByNumber + type: blockdata + proof: alias: eth_getBlockByNumber example: @@ -317,7 +364,7 @@ eth: type: uint returns: descr: the transactiondata or `null` if it does not exist - alias: eth_getTransactionByHash + type: transactiondata proof: alias: eth_getTransactionByHash @@ -369,7 +416,7 @@ eth: type: uint returns: descr: the transactiondata or `null` if it does not exist - alias: eth_getTransactionByHash + type: transactiondata proof: alias: eth_getTransactionByHash @@ -418,50 +465,8 @@ eth: type: bytes32 returns: descr: the transactiondata or `null` if it does not exist - type: - to: - descr: receipient of the transaction. - type: address - from: - descr: sender or signer of the transaction - type: address - value: - descr: value in wei to send - type: uint - gas: - descr: the gas to be send along - type: uint - gasPrice: - descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint - nonce: - descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint - blockHash: - descr: blockHash of the block holding this transaction or `null` if still pending. - type: bytes32 - blockNumber: - descr: blockNumber of the block holding this transaction or `null` if still pending. - type: uint - hash: - descr: transactionHash - type: bytes32 - input: - descr: data of the transaaction - type: bytes - transactionIndex: - descr: index of the transaaction in the block - type: uint - v: - descr: recovery-byte of the signature - type: byte - r: - descr: x-value of the EC-Point of the signature - type: bytes32 - s: - descr: y-value of the EC-Point of the signature - type: bytes32 - + type: transactiondata + example: request: @@ -602,8 +607,6 @@ eth: The merkle-proofs for receipts are created as described in the [Receipt Proof](#eth-gettransactionreceipt). - - If the request requires proof (`verification`: `proof`) the node will provide an Transaction Proof as part of the in3-section of the response. type: type: @@ -990,3 +993,37 @@ eth: - '0xf851a08a14eff77...08080808080808080' - '0xe19f3decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56319' + eth_sendTransaction: + descr: signs and sends a Transaction + params: + tx: + descr: the transactiondata to send + type: transaction + returns: + descr: the transactionHash + proof: + descr: No proof from the nodes are required, because the client can generate the TransactionHash itself. This means to ensure the success of a transaction the receipt needs to be verified. + + eth_sendTransactionAndWait: + descr: signs and sends a Transaction, but then waits until the transaction receipt can be verified. Depending on the finality of the nodes, this may take a while, since only final blocks will be signed by the nodes. + params: + tx: + descr: the transactiondata to send + type: transaction + returns: + descr: the transactionReceipt + type: transactionReceipt + + + eth_sendRawTransaction: + descr: sends or broadcasts a prviously signed raw transaction. See [eth_sendRawTransaction](https://eth.wiki/json-rpc/API#eth_sendRawTransaction) + params: + tx: + descr: the raw signed transactiondata to send + type: bytes + returns: + descr: the transactionhash + type: bytes32 + + + \ No newline at end of file diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml index 4c0a89682..ff7b79e81 100644 --- a/c/src/verifier/eth1/full/rpc.yml +++ b/c/src/verifier/eth1/full/rpc.yml @@ -5,35 +5,7 @@ eth: params: tx: descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - type: - to: - descr: address of the contract - type: address - from: - descr: sender of the address - type: address - optional: true - value: - descr: value in wei to send - type: uint - optional: true - gas: - descr: the gas to be send along - type: uint - optional: true - default: 21000 - gasPrice: - descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint - optional: true - nonce: - descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint - optional: true - data: - descr: the data-section of the transaction, which includes the functionhash and the abi-encoded arguments - type: bytes - optional: true + type: transaction block: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint | string diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml index 79e146c51..180e0c816 100644 --- a/c/src/verifier/eth1/nano/rpc.yml +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -1,3 +1,69 @@ +types: + transactionReceipt: + blockNumber: + descr: the blockNumber + type: uint + blockHash: + descr: blockhash if ther containing block + type: bytes32 + contractAddress: + descr: the deployed contract in case the tx did deploy a new contract + type: address + cumulativeGasUsed: + descr: gas used for all transaction up to this one in the block + type: uint + gasUsed: + descr: gas used by this transaction. + type: uint + logs: + descr: array of events created during execution of the tx + type: + address: + descr: the address triggering the event. + type: address + blockNumber: + descr: the blockNumber + type: uint + blockHash: + descr: blockhash if ther containing block + type: bytes32 + data: + descr: abi-encoded data of the event (all non indexed fields) + type: bytes + logIndex: + descr: the index of the even within the block. + type: uint + removed: + descr: the reorg-status of the event. + type: bool + topics: + descr: array of 32byte-topics of the indexed fields. + type: bytes32[] + transactionHash: + descr: requested transactionHash + type: bytes32 + transactionIndex: + descr: transactionIndex within the containing block. + type: uint + transactionLogIndex: + descr: index of the event within the transaction. + type: uint + type: + descr: mining-status + type: string + logsBloom: + descr: bloomfilter used to detect events for `eth_getLogs` + type: bytes128 + status: + descr: error-status of the tx. 0x1 = success 0x0 = failure + type: uint + transactionHash: + descr: requested transactionHash + type: bytes32 + transactionIndex: + descr: transactionIndex within the containing block. + type: uint + eth: descr: | Standard JSON-RPC calls as described in https://eth.wiki/json-rpc/API. @@ -34,70 +100,7 @@ eth: type: bytes32 returns: descr: the TransactionReceipt or `null` if it does not exist. - type: - blockNumber: - descr: the blockNumber - type: uint - blockHash: - descr: blockhash if ther containing block - type: bytes32 - contractAddress: - descr: the deployed contract in case the tx did deploy a new contract - type: address - cumulativeGasUsed: - descr: gas used for all transaction up to this one in the block - type: uint - gasUsed: - descr: gas used by this transaction. - type: uint - logs: - descr: array of events created during execution of the tx - type: - address: - descr: the address triggering the event. - type: address - blockNumber: - descr: the blockNumber - type: uint - blockHash: - descr: blockhash if ther containing block - type: bytes32 - data: - descr: abi-encoded data of the event (all non indexed fields) - type: bytes - logIndex: - descr: the index of the even within the block. - type: uint - removed: - descr: the reorg-status of the event. - type: bool - topics: - descr: array of 32byte-topics of the indexed fields. - type: bytes32[] - transactionHash: - descr: requested transactionHash - type: bytes32 - transactionIndex: - descr: transactionIndex within the containing block. - type: uint - transactionLogIndex: - descr: index of the event within the transaction. - type: uint - type: - descr: mining-status - type: string - logsBloom: - descr: bloomfilter used to detect events for `eth_getLogs` - type: bytes128 - status: - descr: error-status of the tx. 0x1 = success 0x0 = failure - type: uint - transactionHash: - descr: requested transactionHash - type: bytes32 - transactionIndex: - descr: transactionIndex within the containing block. - type: uint + type: transactionReceipt example: request: diff --git a/c/src/verifier/ipfs/rpc.yml b/c/src/verifier/ipfs/rpc.yml new file mode 100644 index 000000000..ac11faed7 --- /dev/null +++ b/c/src/verifier/ipfs/rpc.yml @@ -0,0 +1,45 @@ +ipfs: + descr: | + A Node supporting IPFS must support these 2 RPC-Methods for uploading and downloading IPFS-Content. The node itself will run a ipfs-client to handle them. + + Fetching ipfs-content can be easily verified by creating the ipfs-hash based on the received data and comparing it to the requested ipfs-hash. Since there is no chance of manipulating the data, there is also no need to put a deposit or convict a node. That's why the registry-contract allows a zero-deposit fot ipfs-nodes. + + ipfs_get: + descr: Fetches the data for a requested ipfs-hash. If the node is not able to resolve the hash or find the data a error should be reported. + params: + ipfshash: + descr: the ipfs multi hash + type: ipfshash + encoding: + descr: the encoding used for the response. ( `hex` , `base64` or `utf8`) + type: string + returns: + descr: the content matching the requested hash encoded in the defined encoding. + proof: + descr: No proof or verification needed on the server side. All the verification are done in the client by creating the ipfs multihash and comparing to the requested hash. + example: + request: + - QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD + - utf8 + response: "I love Incubed" + + ipfs_put: + descr: | + Stores ipfs-content to the ipfs network. + Important! As a client there is no garuantee that a node made this content available. ( just like `eth_sendRawTransaction` will only broadcast it). + Even if the node stores the content there is no gurantee it will do it forever. + params: + data: + descr: the content encoded with the specified encoding. + type: bytes | string + encoding: + descr: the encoding used for the request. ( `hex` , `base64` or `utf8`) + type: string + returns: + descr: the ipfs multi hash + example: + request: + - I love Incubed + - utf8 + response: QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD + From 133506c951eed9aa408e11e83b0e6023977af781 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 08:04:46 +0100 Subject: [PATCH 027/221] added getrawtransaction --- c/src/nodeselect/full/rpc.yml | 2 +- c/src/verifier/btc/rpc.yml | 302 ++++++++++++++++++++++++++++++++++ 2 files changed, 303 insertions(+), 1 deletion(-) diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 7353c0da3..b63e48124 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -115,7 +115,7 @@ in3: # Verified RPCs in3_nodeList: - descr: clears the incubed cache (usually found in the .in3-folder) + descr: fetches and verifies the nodeList from a node params: limit: descr: if the number is defined and >0 this method will return a partial nodeList limited to the given number. diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index fa81d050f..879289d59 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -1,3 +1,96 @@ +types: + btctransaction: + txid: + descr: txid + type: bytes32 + in_active_chain: + descr: Whether specified block is in the active chain or not (only present with explicit "blockhash" argument) + type: bool + hex: + descr: The serialized, hex-encoded data for `txid` + type: bytes + hash: + descr: The transaction hash (differs from txid for witness transactions) + type: bytes32 + size: + descr: The serialized transaction size + type: uint + vsize: + descr: The virtual transaction size (differs from size for witness transactions) + type: uint + weight: + descr: The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) + type: uint + version: + descr: The version + type: uint + locktime: + descr: The lock time + type: uint + vin: + descr: array of json objects of incoming txs to be used + type: + txid: + descr: the transaction id + type: bytes32 + vout: + descr: the index of the transaction out to be used + type: uint + scriptSig: + descr: the script + type: + asm: + descr: the asm-codes + type: string + hex: + descr: hex representation + type: string + sequence: + descr: The script sequence number + type: uint + txinwitness: + descr: hex-encoded witness data (if any) + type: string[] + vout: + descr: array of json objects describing the tx outputs + type: + value: + descr: The Value in BTC + type: uint + n: + descr: the index + type: uint + scriptPubKey: + descr: the script pubkey + type: + asm: + descr: asm + type: string + hex: + descr: hex representation of the script + type: string + reqSigs: + descr: the required signatures + type: uint + type: + descr: The type, eg 'pubkeyhash' + type: string + addresses: + descr: Array of address(each representing a bitcoin adress) + type: string[] + blockhash: + descr: the block hash + type: bytes32 + confirmations: + descr: The confirmations + type: uint + blocktime: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + time: + descr: Same as "blocktime" + type: uint + btc: descr: | *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* @@ -103,7 +196,45 @@ btc: descr: The hash of the next block type: bytes32 + proof: + descr: | + The `proof`-object contains the following properties: + + - for blocks before BIP34 (height < 227,836) and `in3.preBIP34` = false + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + + - for blocks before BIP34 (height < 227,836) and `in3.preBIP34` = true + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) + - **height** - the height of the block (block number) + + - for blocks after BIP34 (height >= 227,836), *the value of `in3.preBIP34` does not matter* + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - **cbtxMerkleProof** - the merkle proof of the coinbase transaction, proofing the correctness of the cbtx. + + Old blocks (height < 227,836) with `in3.preBIP34` disabled cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1)). Old blocks with `in.preBIP34` enabled can be verified by performing a [preBIP34 proof](bitcoin.html#id1). Verifying newer blocks requires multiple proofs. The finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). To verify the block number we are going to perform a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + type: + final: + descr: the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + type: bytes + cbtx: + descr: the serialized coinbase transaction of the block (this is needed to get the verified block number). It will only be included if the blocknumber supports BIP34 and is higher 227,836) + type: bytes + cbtxMerkleProof: + descr: the merkle proof of the coinbase transaction, proofing the correctness of the cbtx. + type: bytes + height: + descr: the height of the block (block number) + type: uint + + example: + in3Params: + finality: 8 + preBIP34: true request: - "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220" - true @@ -128,3 +259,174 @@ btc: final: 0x00e0ff2720723034053c305058beb92ed010...276470 cbtx: 0x0100000000010100000000000000000000000...39da2fc cbtxMerkleProof: 0x6a8077bb4ce76b71d7742ddd368770279a64667b...52e688 + + + + + getblock: + descr: Returns data of block for given block hash. The returned level of details depends on the argument verbosity. + params: + hash: + descr: The block hash + type: bytes32 + verbosity: + descr: 0 or false for hex-encoded data, 1 or true for a json object, and 2 for json object **with** transaction data + type: uint + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + returns: + descr: | + the block. + - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + - verbose `1` or `true`: an object representing the blockheader. + type: + hash: + descr: the block hash (same as provided) + type: bytes32 + confirmations: + descr: The number of confirmations, or -1 if the block is not on the main chain + type: int + height: + descr: The block height or index + type: uint + version: + descr: The block version + type: uint + versionHex: + descr: The block version formatted in hexadecimal + type: hex + merkleroot: + descr: The merkle root ( 32 bytes ) + type: bytes32 + time: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + mediantime: + descr: The median block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + nonce: + descr: The nonce + type: uint + bits: + descr: The bits ( 4 bytes as hex) representing the target + type: bytes4 + difficulty: + descr: The difficulty + type: uint + chainwork: + descr: Expected number of hashes required to produce the current chain (in hex) + type: uint + nTx: + descr: The number of transactions in the block. + type: uint + tx: + descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + type: btctransaction + previousblockhash: + descr: The hash of the previous block + type: bytes32 + nextblockhash: + descr: The hash of the next block + type: bytes32 + + proof: + alias: getblockheader + + example: + in3Params: + finality: 8 + preBIP34: true + request: + - "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220" + - 1 + response: + hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + confirmations: 8268 + height: 624958 + version: 536928256 + versionHex: 2000e000 + merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb + time: 1586333924 + mediantime: 1586332639 + nonce: 1985217615 + bits: 17143b41 + difficulty: 13912524048945.91 + chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 + tx: + - d79ffc80e07fe9e0083319600c59d47afe69995b1357be6e5dba035675780290 + - ... + - 6456819bfa019ba30788620153ea9a361083cb888b3662e2ff39c0f7adf16919 + nTx: 33 + previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 + nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 + in3: + proof: + final: 0x00e0ff2720723034053c305058beb92ed010...276470 + cbtx: 0x0100000000010100000000000000000000000...39da2fc + cbtxMerkleProof: 0x6a8077bb4ce76b71d7742ddd368770279a64667b...52e688 + + getrawtransaction: + descr: Returns the raw transaction data. The returned level of details depends on the argument verbosity. + params: + txid: + descr: The transaction id + type: bytes32 + verbosity: + descr: 0 or false for the hex-encoded data for `txid`, 1 or true for a json object with information about `txid` + type: uint + optional: true + default: 1 + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + returns: + descr: | + - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` + - verbose `1` or `false`: an object representing the transaction. + type: btctransaction + + proof: + descr: | + - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = false + + - `block`: hex - a hex string with 80 bytes representing the blockheader + - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction + + - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = true + + - `block`: hex - a hex string with 80 bytes representing the blockheader + - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) + - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction + - `height`: number - the height of the block (block number) + + - for blocks after BIP34 (height >= 227836), *the value of `in3.preBIP34` does not matter* + + - `block`: hex - a hex string with 80 bytes representing the blockheader + - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction + - `cbtx`: hex - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - `cbtxMerkleProof`: hex - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` + + + Transactions of old blocks (height < 227836) with `in3.preBIP34` disabled cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1) and relying on the merkle proof is only possible when the block is final). Transactions of old blocks with `in3.preBIP34` enabled can be verified by performing a [preBIP34 proof](bitcoin.html#id1) and a [merkle proof](bitcoin.html#transaction-proof-merkle-proof). Verifying newer blocks requires multiple proofs. The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). By doing a [merkle proof](bitcoin.html#transaction-proof-merkle-proof) using the `txIndex`-field and the `merkleProof`-field the correctness of the requested transation can be proven. Furthermore we are going to perform a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + + From 08f6b0d5d3018b9609bb0fc7bc54dd4a7ecbfff1 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 08:05:00 +0100 Subject: [PATCH 028/221] optimized script --- scripts/build_rpc_docu.js | 61 ++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 5902114a4..961d0bb59 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -1,9 +1,7 @@ const yaml = require('../wasm/test/node_modules/yaml') const fs = require('fs') -const docs = {} -let config = {} -let types = {} +let docs = {}, config = {}, types = {} const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' const getType = val => typeof val === 'object' ? val : (types['' + val] || val) @@ -24,26 +22,27 @@ function scan(dir) { else if (f.isDirectory()) scan(dir + '/' + f.name) } } -function print_object(def, pad) { +function print_object(def, pad, useNum) { + let i = 1 for (const prop of Object.keys(def)) { - let s = pad + '* **' + prop + '**' + let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' const p = def[prop] const pt = getType(p.type) if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' if (p.optional) s += ' *(optional)*' if (p.descr) s += ' - ' + p.descr if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' + if (p.alias) s += '\n' + pad + 'The data structure of ' + prop + ' is the same as ' + link(p.alias) + '. See Details there.' console.log(s) if (typeof pt === 'object') { console.log('The ' + prop + ' object supports the following properties :\n' + pad) print_object(pt, pad + ' ') } - if (p.example) console.log('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) console.log(pad + '\n') } - } + scan('../c/src') docs.in3.in3_config.params.config.type = config console.log('# API RPC\n\n') @@ -61,29 +60,20 @@ for (const s of Object.keys(docs).sort()) { if (def.descr) console.log(def.descr + '\n') if (def.params) { console.log("*Parameters:*\n") - let i = 1 - for (const par of Object.keys(def.params)) { - const p = def.params[par] - const pt = getType(p.type) - let s = (i++) + '. **' + par + '**' - if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' - if (p.descr) s += ' - ' + p.descr - if (p.alias) s += ' The data structure of ' + par + ' is the same as ' + link(def.returns.alias) + '. See Details there.' - console.log(s) - if (typeof pt === 'object') { - console.log('\nThe ' + par + ' params support the following properties :\n') - print_object(pt, '') - } - - } + print_object(def.params, '', true) console.log() } else if (!def.alias) console.log("*Parameters:* - \n") + if (def.in3Params) { + console.log('The following in3-configuration will have an impact on the result:\n\n'); + print_object(getType(def.in3Params), '') + console.log() + } if (def.returns) { if (def.returns.type) { - console.log('*Returns:* ' + (typeof def.returns.type === 'string' ? def.returns.type : 'object') + '\n\n' + def.returns.descr + '\n') + console.log('*Returns:* ' + (typeof def.returns.type === 'string' ? ('`' + def.returns.type + '`') : '`object`') + '\n\n' + def.returns.descr + '\n') const pt = getType(def.returns.type) if (typeof pt === 'object') { console.log('\nThe return value contains the following properties :\n') @@ -109,23 +99,22 @@ for (const s of Object.keys(docs).sort()) { } } - - asArray(def.example).forEach(ex => { const req = { method: rpc, params: ex.request || [] } - if (def.proof) req.in3 = { "verification": "proof" } - console.log('*Request:*\n') - console.log('```js\n' + JSON.stringify(req, null, 2)) + if (def.proof) req.in3 = { "verification": "proof", ...ex.in3Params } + const data = { result: ex.response || null } + if (ex.in3) data.in3 = ex.in3 + + console.log('*Example:*\n') + + console.log('```js\n//---- Request -----\n\n' + JSON.stringify(req, null, 2)) + console.log('\n//---- Response -----\n\n' + JSON.stringify(data, null, 2)) console.log('```\n') - if (ex.response) { - const data = { result: ex.response } - if (ex.in3) data.in3 = ex.in3 - console.log('*Response:*\n') - console.log('```js\n' + JSON.stringify(data, null, 2)) - console.log('```\n') - } - }) + console.log('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) + console.log('\n# ---- Response -----\n\n' + yaml.stringify(data)) + console.log('```\n') + }) } } From 5cdd940b41ad1feffd45f8ef36f079ba9828a621 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 09:17:44 +0100 Subject: [PATCH 029/221] finish btc --- c/src/verifier/btc/rpc.yml | 324 +++++++++++++++++++++++++++++++++++-- 1 file changed, 308 insertions(+), 16 deletions(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 879289d59..ad57d636e 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -384,6 +384,10 @@ btc: type: uint optional: true default: 1 + blockhash: + descr: The block in which to look for the transaction + type: bytes32 + optional: true in3Params: finality: descr: defines the amount of finality headers @@ -404,29 +408,317 @@ btc: descr: | - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = false - - `block`: hex - a hex string with 80 bytes representing the blockheader - - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) - - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) - - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **txIndex** - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - **merkleProof** - the merkle proof of the requested transaction, proving the correctness of the transaction - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = true - - `block`: hex - a hex string with 80 bytes representing the blockheader - - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) - - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) - - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction - - `height`: number - the height of the block (block number) + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) + - **txIndex** - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - **merkleProof** - the merkle proof of the requested transaction, proving the correctness of the transaction + - **height** - the height of the block (block number) - for blocks after BIP34 (height >= 227836), *the value of `in3.preBIP34` does not matter* - - `block`: hex - a hex string with 80 bytes representing the blockheader - - `final`: hex - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) - - `txIndex`: number - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) - - `merkleProof`: hex - the merkle proof of the requested transaction, proving the correctness of the transaction - - `cbtx`: hex - the serialized coinbase transaction of the block (this is needed to get the verified block number) - - `cbtxMerkleProof`: hex - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **txIndex** - index of the transaction (`txIndex`=`0` for coinbase transaction, necessary to create/verify the merkle proof) + - **merkleProof** - the merkle proof of the requested transaction, proving the correctness of the transaction + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - **cbtxMerkleProof** - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` Transactions of old blocks (height < 227836) with `in3.preBIP34` disabled cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1) and relying on the merkle proof is only possible when the block is final). Transactions of old blocks with `in3.preBIP34` enabled can be verified by performing a [preBIP34 proof](bitcoin.html#id1) and a [merkle proof](bitcoin.html#transaction-proof-merkle-proof). Verifying newer blocks requires multiple proofs. The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). By doing a [merkle proof](bitcoin.html#transaction-proof-merkle-proof) using the `txIndex`-field and the `merkleProof`-field the correctness of the requested transation can be proven. Furthermore we are going to perform a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + example: + in3Params: + finality: 8 + request: + - 'f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf' + - true + - '000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220' + response: + in_active_chain: true + txid: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf + hash: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf + version: 1 + size: 518 + vsize: 518 + weight: 2072 + locktime: 0 + vin: + - txid: 0a74f6e5f99bc69af80da9f0d9878ea6afbfb5fbb2d43f1ff899bcdd641a098c + vout: 0 + scriptSig: + asm: 30440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228cc...254874 + hex: 4730440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228...254874 + sequence: 4294967295 + - txid: 869c5e82d4dfc3139c8a153d2ee126e30a467cf791718e6ea64120e5b19e5044 + vout: 0 + scriptSig: + asm: 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d + hex: 483045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745...f3255d + sequence: 4294967295 + - txid: 8a03d29a1b8ae408c94a2ae15bef8329bc3d6b04c063d36b2e8c997273fa8eff + vout: 1 + scriptSig: + asm: 304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d1284...0045da + hex: 47304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d12...0045da + sequence: 4294967295 + vout: + - value: 0.00017571 + n: 0 + scriptPubKey: + asm: OP_DUP OP_HASH160 53196749b85367db9443ef9a5aec25cf0bdceedf OP_EQUALVERIFY + OP_CHECKSIG + hex: 76a91453196749b85367db9443ef9a5aec25cf0bdceedf88ac + reqSigs: 1 + type: pubkeyhash + addresses: + - 18aPWzBTq1nzs9o86oC9m3BQbxZWmV82UU + - value: 0.00915732 + n: 1 + scriptPubKey: + asm: OP_HASH160 8bb2b4b848d0b6336cc64ea57ae989630f447cba OP_EQUAL + hex: a9148bb2b4b848d0b6336cc64ea57ae989630f447cba87 + reqSigs: 1 + type: scripthash + addresses: + - 3ERfvuzAYPPpACivh1JnwYbBdrAjupTzbw + hex: '01000000038c091a64ddbc99f81f3fd4b2fbb5bfafa68e8...000000' + blockhash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + confirmations: 15307 + time: 1586333924 + blocktime: 1586333924 + in3: + proof: + block: 0x00e00020497f4c193dbb347c2ecfcf6169e64c747877...045476 + final: 0x00e0ff2720723034053c305058beb92ed0101b2294cd...276470 + txIndex: 7 + merkleProof: 0x348d4bb04943400a80f162c4ef64b746bc4af0...52e688 + cbtx: 0x010000000001010000000000000000000000000000000...9da2fc + cbtxMerkleProof: 0x6a8077bb4ce76b71d7742ddd368770279a...52e688 + + getblockcount: + descr: Returns the number of blocks in the longest blockchain. + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + returns: + descr: the current blockheight + type: uint + proof: + descr: | + Since we can't prove the finality of the latest block we consider the `current block count` - `amount of finality` (set in `in3.finality`-field) as the latest block. The number of this block will be returned. Setting `in3.finality`=`0` will return the actual current block count. + + The `proof`-object contains the following properties: + + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - vcbtxMerkleProof** - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` + + + The server is not able to prove the finality for the latest block (obviously there are no finality headers available yet). Instead the server will fetch the number of the latest block and subtracts the amount of finality headers (set in `in3.finality`-field) and returns the result to the client (the result is considered as the latest block number). By doing so the server is able to provide finality headers. \ + The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). Having a verified block header (and therefore a verified merkle root) enables the possibility of a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + + The client can set `in3.finality` equal to `0` to get the actual latest block number. **Caution**: This block is not final and could no longer be part of the blockchain later on due to the possibility of a fork. Additionally, there may already be a newer block that the server does not yet know about due to latency in the network. + example: + descr: The actual latest block is block `#640395` and `in3.finality` is set to `8`. The server is going to calculate `640395` - `8` and returns `640387` as the latest block number to the client. The headers of block `640388`..`640395` will be returned as finality headers. + in3Params: + finality: 8 + response: 640387 + in3: + proof: + block: "0x0000e020bd3eecbd741522e1aa78cd7b375744590502939aef9b...9c8b18" + final: "0x00008020f61dfcc47a6daed717b12221855196dee02d844ebb9c...774f4c" + cbtx: "0x02000000000101000000000000000000000000000000000000000...000000" + cbtxMerkleProof: "0xa3d607b274770911e53f06dbdb76440580ff968239...0ba297" + + + + getdifficulty: + descr: Returns the proof-of-work difficulty as a multiple of the minimum difficulty. + params: + blocknumber: + descr: 'Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`)' + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + + returns: + descr: | + - `blocknumber` is a certain number: the difficulty of this block + - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) + + proof: + descr: | + The `proof`-object contains the following properties: + + - for blocks before BIP34 (height < 227,836) and `in3.preBIP34` = false + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + + - for blocks before BIP34 (height < 227,836) and `in3.preBIP34` = true + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) + - **height** - the height of the block (block number) + + - for blocks after BIP34 (height >= 227,836), *the value of `in3.preBIP34` does not matter* + + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - **cbtxMerkleProof** - the merkle proof of the coinbase transaction, proofing the correctness of the cbtx. + + In case the client requests the diffictuly of a certain block (`blocknumber` is a certain number) the `block`-field will contain the block header of this block and the `final`-field the corresponding finality headers. For old blocks (height < 227,836) with `in3.preBIP34` disabled the result cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1)). The result of old blocks with `in.preBIP34` enabled can be verified by performing a [preBIP34 proof](bitcoin.html#id1). In case the client requests the difficulty of the latest block the server is not able to prove the finality for this block (obviously there are no finality headers available yet). The server considers the latest block minus `in3.finality` as the latest block and returns its difficulty. The result can be verified by performing multiple proof. The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). Having a verified block header (and therefore a verified merkle root) enables the possibility of a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + + The result itself (the difficulty) can be verified in two ways: + - by converting the difficulty into a target and check whether the block hash is lower than the target (since we proved the finality we consider the block hash as verified) + - by converting the difficulty and the bits (part of the block header) into a target and check if both targets are similar (they will not be equal since the target of the bits is not getting saved with full precision - leading bytes are equal) + type: + final: + descr: the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + type: bytes + cbtx: + descr: the serialized coinbase transaction of the block (this is needed to get the verified block number). It will only be included if the blocknumber supports BIP34 and is higher 227,836) + type: bytes + cbtxMerkleProof: + descr: the merkle proof of the coinbase transaction, proofing the correctness of the cbtx. + type: bytes + height: + descr: the height of the block (block number) + type: uint + example: + in3Params: + finality: 8 + request: + - 631910 + response: 15138043247082.88 + in3: + proof: + block: "0x0000e020bd3eecbd741522e1aa78cd7b375744590502939aef9b...9c8b18" + final: "0x00008020f61dfcc47a6daed717b12221855196dee02d844ebb9c...774f4c" + cbtx: "0x02000000000101000000000000000000000000000000000000000...000000" + cbtxMerkleProof: "0xa3d607b274770911e53f06dbdb76440580ff968239...0ba297" + + in3_proofTarget: + descr: Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. + params: + target_dap: + descr: the number of the difficulty adjustment period (dap) we are looking for + type: uint + verified_dap: + descr: the number of the closest already verified dap + type: uint + max_diff: + descr: the maximum target difference between 2 verified daps + type: uint + max_dap: + descr: the maximum amount of daps between 2 verified daps + type: uint + limit: + descr: the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory + type: uint + optional: true + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + validation: | + Hints: + + - difference between `target_dap` and `verified_dap` should be greater than `1` + - `target_dap` and `verified_dap` have to be greater than `0` + - `limit` will be set to `40` internaly when the parameter is equal to `0` or greater than `40` + - `max_dap` can't be equal to `0` + - `max_diff` equal to `0` means no tolerance regarding the change of the target - the path will contain every dap between `target_dap` and `verified_dap` (under consideration of `limit`) + - total possible amount of finality headers (`in3.finaliy` \* `limit`) can't be greater than `1000` + - changes of a target will always be accepted if it decreased from one dap to another (i.e. difficulty to mine a block increased) + - in case a dap that we want to verify next (i.e. add it to the path) is only 1 dap apart from a verified dap (i.e. `verified_dap` or latest dap of the path) *but* not within the given limit (`max_diff`) it will still be added to the path (since we can't do even smaller steps) + + This graph shows the usage of this method and visualizes the result from above. The client is not able to trust the changes of the target due to his limits (`max_diff` and `max_dap`). This method provides a path of daps in which the limits are fulfilled from dap to another. The client is going to trust the target of the target dap since he is able to perform a step by step verification of the target by using the path of daps. + + ![](proofTarget.png) + + returns: + descr: A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. + proof: + descr: | + Each `dap`-object contains the following properties: + + - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = false + + - **dap** - the numer of the difficulty adjustment period + - **block** - a hex string with 80 bytes representing the (always the first block of a dap) + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + + - for blocks before BIP34 (height < 227836) and `in3.preBIP34` = true + + - **dap** - the numer of the difficulty adjustment period + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated up to the next checkpoint (maximum of 200 finality headers, since the distance between checkpoints = 200) + - **height** - the height of the block (block number) + + - for blocks after BIP34 (height >= 227836), *the value of `in3.preBIP34` does not matter* + + - **dap** - the numer of the difficulty adjustment period + - **block** - a hex string with 80 bytes representing the (always the first block of a dap) + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - **cbtxMerkleProof** - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` + + The goal is to verify the target of the `target_dap`. We will use the daps of the result to verify the target step by step starting with the `verified_dap`. For old blocks (height < 227,836) with `in3.preBIP34` disabled the target cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1)). For old blocks with `in.preBIP34` enabled the block header can be verified by performing a [preBIP34 proof](bitcoin.html#id1). Verifying newer blocks requires multiple proofs. The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). Having a verified block header allows us to consider the target of the block header as verified. Therefore, we have a verified target for the whole `dap`. Having a verified block header (and therefore a verified merkle root) enables the possibility of a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). This proof is needed to verify the dap number (`dap`). Having a verified dap number allows us to verify the mapping between the target and the dap number. + example: + request: + - 230 + - 200 + - 5 + - 5 + - 15 + response: + - dap: 205 + block: 0x04000000e62ef28cb9793f4f9cd2a67a58c1e7b593129b9b...0ab284 + final: 0x04000000cc69b68b702321adf4b0c485fdb1f3d6c1ddd140...090a5b + cbtx: 0x01000000...1485ce370573be63d7cc1b9efbad3489eb57c8...000000 + cbtxMerkleProof: 0xc72dffc1cb4cbeab960d0d2bdb80012acf7f9c...affcf4 + - dap: 210 + block: 0x0000003021622c26a4e62cafa8e434c7e083f540bccc8392...b374ce + final: 0x00000020858f8e5124cd516f4d5e6a078f7083c12c48e8cd...308c3d + cbtx: 0x01000000...c075061b4b6e434d696e657242332d50314861...000000 + cbtxMerkleProof: 0xf2885d0bac15fca7e1644c1162899ecd43d52b...93761d + - dap: 215 + block: 0x000000202509b3b8e4f98290c7c9551d180eb2a463f0b978...f97b64 + final: 0x0000002014c7c0ed7c33c59259b7b508bebfe3974e1c99a5...eb554e + cbtx: 0x01000000...90133cf94b1b1c40fae077a7833c0fe0ccc474...000000 + cbtxMerkleProof: 0x628c8d961adb157f800be7cfb03ffa1b53d3ad...ca5a61 + - dap: 220 + block: 0x00000020ff45c783d09706e359dcc76083e15e51839e4ed5...ddfe0e + final: 0x0000002039d2f8a1230dd0bee50034e8c63951ab812c0b89...5670c5 + cbtx: 0x01000000...b98e79fb3e4b88aefbc8ce59e82e99293e5b08...000000 + cbtxMerkleProof: 0x16adb7aeec2cf254db0bab0f4a5083fb0e0a3f...63a4f4 + - dap: 225 + block: 0x02000020170fad0b6b1ccbdc4401d7b1c8ee868c6977d6ce...1e7f8f + final: 0x0400000092945abbd7b9f0d407fcccbf418e4fc20570040c...a9b240 + cbtx: 0x01000000...cf6e8f930acb8f38b588d76cd8c3da3258d5a7...000000 + cbtxMerkleProof: 0x25575bcaf3e11970ccf835e88d6f97bedd6b85...bfdf46 + - From 779b60abdd66f7330c61b1096b67783f5bf78a7a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 12:31:48 +0100 Subject: [PATCH 030/221] finished all rpcs --- c/src/pay/zksync/rpc.yml | 497 ++++++++++++++++++++++++++++++++++++- c/src/verifier/btc/rpc.yml | 52 ++++ scripts/build_rpc_docu.js | 16 +- 3 files changed, 561 insertions(+), 4 deletions(-) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index f5b22d507..c5276f049 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -65,6 +65,501 @@ zksync: descr: the hash of the actual deploy-tx including the constructor-arguments. type: bytes32 + # rpc + zksync_contract_address: + descr: returns the contract address + returns: + descr: fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. + type: + govContract: + descr: the address of the govement contract + type: address + mainContract: + descr: the address of the main contract + type: address + example: + cmdParams: -x + response: + govContract: "0x34460C0EB5074C29A9F6FE13b8e7E23A0D08aF01" + mainContract: "0xaBEA9132b05A70803a4E85094fD0e1800777fBEF" + + + zksync_tokens: + descr: returns the list of all available tokens + returns: + descr: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. + type: + address: + descr: the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) + type: address + decimals: + descr: decimals to be used when formating it for human readable representation. + type: uint + id: + descr: id which will be used when encoding the token. + type: uint + symbol: + descr: symbol for the token + type: string + example: + cmdParams: -x + response: + BAT: + address: '0x0d8775f648430679a709e98d2b0cb6250d2887ef' + decimals: 18 + id: 8 + symbol: BAT + BUSD: + address: '0x4fabb145d64652a948d72533023f6e7a623c7c53' + decimals: 18 + id: 6 + symbol: BUSD + DAI: + address: '0x6b175474e89094c44da98b954eedeac495271d0f' + decimals: 18 + id: 1 + symbol: DAI + ETH: + address: '0x0000000000000000000000000000000000000000' + decimals: 18 + id: 0 + symbol: ETH + + zksync_account_info: + descr: returns account_info from the server + params: + address: + descr: the account-address. if not specified, the client will try to use its own address based on the signer config. + type: address + optional: true + returns: + descr: the current state of the requested account. + type: + address: + descr: the address of the account + type: address + commited: + descr: the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. + type: + balances: + descr: the token-balances. + type: + : + descr: the balance of the token + type: uint + nonce: + descr: the nonce or transaction count. + type: uint + pubKeyHash: + descr: the pubKeyHash set for the requested account or `0x0000...` if not set yet. + type: address + depositing: + descr: the state of all depositing-tx. + type: + balances: + descr: the token-values. + type: + : + descr: the value of the token + type: uint + id: + descr: the assigned id of the account, which will be used when encoding it into the rollup. + type: uint + verified: + descr: the state after the rollup was verified in L1. + type: + balances: + descr: the token-balances. + type: + : + descr: the balance of the token + type: uint + nonce: + descr: the nonce or transaction count. + type: uint + pubKeyHash: + descr: the pubKeyHash set for the requested account or `0x0000...` if not set yet. + type: address + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + response: + address: '0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292' + committed: + balances: {} + nonce: 0 + pubKeyHash: sync:0000000000000000000000000000000000000000 + depositing: + balances: {} + id: + verified: + balances: {} + nonce: 0 + pubKeyHash: sync:0000000000000000000000000000000000000000 + + + zksync_tx_info: + descr: returns the state or receipt of the the zksync-tx + params: + tx: + descr: the txHash of the send tx + type: bytes32 + returns: + descr: the current state of the requested tx. + type: + block: + descr: the blockNumber containing the tx or `null` if still pending + type: uint + executed: + descr: true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. + type: bool + success: + descr: if executed, this property marks the success of the tx. + type: bool + failReason: + descr: if executed and failed this will include an error message + type: string + example: + cmdParams: -x + request: + - "sync-tx:e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000" + response: + block: null + executed: false + failReason: null + success: null + + zksync_set_key: + descr: | + sets the signerkey based on the current pk or as configured in the config. + You can specify the key by either + - setting a signer ( the sync key will be derrived through a signature ) + - setting the seed directly ( `sync_key` in the config) + - setting the `musig_pub_keys` to generate the pubKeyHash based on them + - setting the `create2` options and the sync-key will generate the account based on the pubKeyHash + + + we support 3 different signer types (`signer_type` in the `zksync` config) : + + 1. `pk` - Simple Private Key + If a signer is set (for example by setting the pk), incubed will derrive the sync-key through a signature and use it + 2. `contract` - Contract Signature + In this case a preAuth-tx will be send on L1 using the signer. If this contract is a mutisig, you should make sure, you have set the account explicitly in the config and also activate the multisig-plugin, so the transaction will be send through the multisig. + 3. `create2` - Create2 based Contract + + params: + token: + descr: the token to pay the gas (either the symbol or the address) + type: string + returns: + descr: the pubKeyHash, if it was executed successfully + type: address + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + request: + - eth + response: "sync:e41d2489571d322189246dafa5ebde1f4699f498" + + zksync_pubkeyhash: + descr: returns the current PubKeyHash based on the configuration set. + params: + pubKey: + descr: the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) + type: bytes32 + optional: true + returns: + descr: the pubKeyHash + type: address + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + response: "sync:4dcd9bb4463121470c7232efb9ff23ec21398e58" + + + zksync_pubkey: + descr: | + returns the current packed PubKey based on the config set. + + If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. + returns: + descr: the pubKey + type: bytes32 + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + response: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc04" + + + + zksync_account_address: + descr: returns the address of the account used. + returns: + descr: the account used. + type: address + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + response: "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" + + + + + zksync_sign: + descr: | + returns the schnorr musig signature based on the current config. + + This also supports signing with multiple keys. In this case the configuration needs to sets the urls of the other keys, so the client can then excange all data needed in order to create the combined signature. + when exchanging the data with other keys, all known data will be send using `zk_sign` as method, but instead of the raw message a object with those data will be passed. + + params: + message: + descr: the message to sign + type: bytes + returns: + descr: | + The return value are 96 bytes of signature: + - `[0...32]` packed public key + - `[32..64]` r-value + - `[64..96]` s-value + type: bytes96 + example: + cmdParams: -x -pk 0xe41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000 + request: + - '0xaabbccddeeff' + response: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01" + + zksync_verify: + descr: | + returns 0 or 1 depending on the successfull verification of the signature. + + if the `musig_pubkeys` are set it will also verify against the given public keys list. + + params: + message: + descr: the message which was supposed to be signed + type: bytes + signature: + descr: the signature (96 bytes) + type: bytes96 + returns: + descr: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. + type: uint + example: + cmdParams: -x + request: + - '0xaabbccddeeff' + - '0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01' + response: 1 + + zksync_ethop_info: + descr: returns the state or receipt of the the PriorityOperation + params: + opId: + descr: the opId of a layer-operstion (like depositing) + type: uint + + zksync_get_token_price: + descr: returns current token-price + params: + token: + descr: Symbol or address of the token + type: string + returns: + descr: the token price + type: float + example: + cmdParams: -x + request: + - WBTC + response: 11320.002167 + + zksync_get_tx_fee: + descr: calculates the fees for a transaction. + params: + txType: + descr: The Type of the transaction "Withdraw" or "Transfer" + type: string + address: + descr: the address of the receipient + type: address + token: + descr: the symbol or address of the token to pay + type: string + returns: + descr: the fees split up into single values + type: + feeType: + descr: Type of the transaaction + type: string + gasFee: + descr: the gas for the core-transaction + type: uint + gasPriceWei: + descr: current gasPrice + type: uint + gasTxAmount: + descr: gasTxAmount + type: uint + totalFee: + descr: total of all fees needed to pay in order to execute the transaction + type: uint + zkpFee: + descr: zkpFee + type: uint + example: + cmdParams: -x + request: + - Transfer + - '0xabea9132b05a70803a4e85094fd0e1800777fbef' + - BAT + response: + feeType: "TransferToNew" + gasFee: "47684047990828528" + gasPriceWei: "116000000000" + gasTxAmount: "350" + totalFee: "66000000000000000" + zkpFee: "18378682992117666" + + zksync_sync_key: + descr: returns private key used for signing zksync-transactions + returns: + descr: the raw private key configured based on the signers seed + example: + cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c + response: '0x019125314fda133d5bf62cb454ee8c60927d55b68eae8b8b8bd13db814389cd6' + + zksync_deposit: + descr: sends a deposit-transaction and returns the opId, which can be used to tradck progress. + params: + amount: + descr: the value to deposit in wei (or smallest token unit) + type: uint + token: + descr: the token as symbol or address + type: string + approveDepositAmountForERC20: + descr: if true and in case of an erc20-token, the client will send a approve transaction first, otherwise it is expected to be already approved. + type: bool + optional: true + account: + descr: address of the account to send the tx from. if not specified, the first available signer will be used. + type: address + optional: true + returns: + descr: the opId. You can use `zksync_ethop_info` to follow the state-changes. + type: uint + example: + cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c + request: + - 1000 + - WBTC + response: 74 + + zksync_transfer: + descr: sends a zksync-transaction and returns data including the transactionHash. + params: + to: + descr: the receipient of the tokens + type: address + amount: + descr: the value to transfer in wei (or smallest token unit) + type: uint + token: + descr: the token as symbol or address + type: string + account: + descr: address of the account to send the tx from. if not specified, the first available signer will be used. + type: address + optional: true + returns: + descr: the transactionHash. use `zksync_tx_info` to check the progress. + type: bytes32 + example: + cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c + request: + - 0xabea9132b05a70803a4e85094fd0e1800777fbef + - 100 + - WBTC + response: '0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1' + + zksync_withdraw: + descr: withdraws the amount to the given `ethAddress` for the given token. + params: + ethAddress: + descr: the receipient of the tokens in L1 + type: address + amount: + descr: the value to transfer in wei (or smallest token unit) + type: uint + token: + descr: the token as symbol or address + type: string + account: + descr: address of the account to send the tx from. if not specified, the first available signer will be used. + type: address + optional: true + returns: + descr: the transactionHash. use `zksync_tx_info` to check the progress. + type: bytes32 + example: + cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c + request: + - 0xabea9132b05a70803a4e85094fd0e1800777fbef + - 100 + - WBTC + response: '0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1' + + zksync_emergency_withdraw: + descr: withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. + params: + token: + descr: the token as symbol or address + type: string + returns: + descr: the transactionReceipt + type: transactionReceipt + example: + cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c + request: + - WBTC + response: + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + contractAddress: + cumulativeGasUsed: '0x2466d' + gasUsed: '0x2466d' + logs: + - address: '0x85ec283a3ed4b66df4da23656d4bf8a507383bca' + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + data: 0x00000000000... + logIndex: '0x0' + removed: false + topics: + - '0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8' + - '0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6' + - '0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + transactionLogIndex: '0x0' + type: mined + logsBloom: 0x00000000000000000000200000... + root: + status: '0x1' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + + zksync_aggregate_pubkey: + descr: calculate the public key based on multiple public keys signing together using schnorr musig signatures. + params: + pubkeys: + descr: concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` + type: bytes + returns: + descr: the compact public Key + type: bytes32 + example: + cmdParams: -x + request: + - '0x0f61bfe164cc43b5a112bfbfb0583004e79dbfafc97a7daad14c5d511fea8e2435065ddd04329ec94be682bf004b03a5a4eeca9bf50a8b8b6023942adc0b3409' + response: '0x9ce5b6f8db3fbbe66a3bdbd3b4731f19ec27f80ee03ead3c0708798dd949882b' + + - diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index ad57d636e..f90a3d18a 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -235,6 +235,7 @@ btc: in3Params: finality: 8 preBIP34: true + cmdParams: -x -c btc -f 8 request: - "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220" - true @@ -344,6 +345,7 @@ btc: in3Params: finality: 8 preBIP34: true + cmdParams: -x -c btc -f 8 request: - "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220" - 1 @@ -435,6 +437,7 @@ btc: example: in3Params: finality: 8 + cmdParams: -x -c btc -f 8 request: - 'f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf' - true @@ -533,6 +536,7 @@ btc: descr: The actual latest block is block `#640395` and `in3.finality` is set to `8`. The server is going to calculate `640395` - `8` and returns `640387` as the latest block number to the client. The headers of block `640388`..`640395` will be returned as finality headers. in3Params: finality: 8 + cmdParams: -x -c btc -f 8 response: 640387 in3: proof: @@ -604,6 +608,7 @@ btc: example: in3Params: finality: 8 + cmdParams: -x -c btc -f 8 request: - 631910 response: 15138043247082.88 @@ -688,6 +693,7 @@ btc: The goal is to verify the target of the `target_dap`. We will use the daps of the result to verify the target step by step starting with the `verified_dap`. For old blocks (height < 227,836) with `in3.preBIP34` disabled the target cannot be verified (proving the finality does not provide any security as explained in [preBIP34 proof](bitcoin.html#id1)). For old blocks with `in.preBIP34` enabled the block header can be verified by performing a [preBIP34 proof](bitcoin.html#id1). Verifying newer blocks requires multiple proofs. The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). Having a verified block header allows us to consider the target of the block header as verified. Therefore, we have a verified target for the whole `dap`. Having a verified block header (and therefore a verified merkle root) enables the possibility of a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). This proof is needed to verify the dap number (`dap`). Having a verified dap number allows us to verify the mapping between the target and the dap number. example: + cmdParams: -x -c btc -f 8 request: - 230 - 200 @@ -722,3 +728,49 @@ btc: cbtxMerkleProof: 0x25575bcaf3e11970ccf835e88d6f97bedd6b85...bfdf46 + getbestblockhash: + descr: Returns the hash of the best (tip) block in the longest blockchain. + in3Params: + finality: + descr: defines the amount of finality headers + type: uint + verification: + descr: defines the kind of proof the client is asking for (must be `never` or `proof`) + type: string + preBIP34: + descr: defines if the client wants to verify blocks before BIP34 (height < 227836) + type: bool + returns: + descr: the hash of the best block + type: bytes32 + proof: + descr: | + Since we can't prove the finality of the latest block we consider the `current block count` - `amount of finality` (set in `in3.finality`-field) as the latest block. The hash of this block will be returned. Setting `in3.finality`=`0` will return will return the hash of the actual latest block. + + The `proof`-object contains the following properties: + + - **block** - a hex string with 80 bytes representing the blockheader + - **final** - the finality headers, which are hexcoded bytes of the following headers (80 bytes each) concatenated, the number depends on the requested finality (`finality`-property in the `in3`-section of the request) + - **cbtx** - the serialized coinbase transaction of the block (this is needed to get the verified block number) + - **cbtxMerkleProof* - the merkle proof of the coinbase transaction, proving the correctness of the `cbtx` + + The server is not able to prove the finality for the latest block (obviously there are no finality headers available yet). Instead the server will fetch the number of the latest block and subtracts the amount of finality headers (set in `in3.finality`-field) and returns the hash of this block to the client (the result is considered as the latest block hash). By doing so the server is able to provide finality headers. \ + The block header from the `block`-field and the finality headers from the `final`-field will be used to perform a [finality proof](bitcoin.html#finality-proof). Having a verified block header (and therefore a verified merkle root) enables the possibility of a [block number proof](bitcoin.html#block-number-proof) using the coinbase transaction (`cbtx`-field) and the [merkle proof](bitcoin.html#transaction-proof-merkle-proof) for the coinbase transaction (`cbtxMerkleProof`-field). + + The client can set `in3.finality` equal to `0` to get the actual latest block hash. **Caution**: This block is not final and could no longer be part of the blockchain later on due to the possibility of a fork. Additionally, there may already be a newer block that the server does not yet know about due to latency in the network. + example: + cmdParams: -x -c btc -f 8 + descr: The actual latest block is block `#640395` and `in3.finality` is set to `8`. The server is going to calculate `640395` - `8` and returns the hash of block `#640387` to the client. The headers of block `640388`..`640395` will be returned as finality headers. + in3Params: + finality: 8 + response: '000000000000000000039cbb4e842de0de9651852122b117d7ae6d7ac4fc1df6' + in3: + proof: + block: "0x0000e020bd3eecbd741522e1aa78cd7b375744590502939aef9b...9c8b18" + final: "0x00008020f61dfcc47a6daed717b12221855196dee02d844ebb9c...774f4c" + cbtx: "0x02000000000101000000000000000000000000000000000000000...000000" + cbtxMerkleProof: "0xa3d607b274770911e53f06dbdb76440580ff968239...0ba297" + + + + diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 961d0bb59..44ccd206f 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -5,6 +5,7 @@ let docs = {}, config = {}, types = {} const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' const getType = val => typeof val === 'object' ? val : (types['' + val] || val) +const toCmdParam = val => (typeof val == 'object' || Array.isArray(val) || ('' + val).indexOf(' ') >= 0) ? "'" + JSON.stringify(val) + "'" : ('' + val) function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { @@ -70,6 +71,7 @@ for (const s of Object.keys(docs).sort()) { print_object(getType(def.in3Params), '') console.log() } + if (def.validation) console.log('\n' + def.validation + '\n') if (def.returns) { if (def.returns.type) { @@ -103,17 +105,25 @@ for (const s of Object.keys(docs).sort()) { const req = { method: rpc, params: ex.request || [] } if (def.proof) req.in3 = { "verification": "proof", ...ex.in3Params } const data = { result: ex.response || null } + const is_json = (typeof data.result == 'object' || Array.isArray(data.result)) if (ex.in3) data.in3 = ex.in3 console.log('*Example:*\n') + if (ex.descr) console.log('\n' + ex.descr + '\n') + + /* + console.log('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) + console.log('\n# ---- Response -----\n\n' + yaml.stringify(data)) + console.log('```\n') + */ + console.log('```sh\n> in3 ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) + console.log(is_json ? JSON.stringify(data.result, null, 2) : '' + data.result) + console.log('```\n') console.log('```js\n//---- Request -----\n\n' + JSON.stringify(req, null, 2)) console.log('\n//---- Response -----\n\n' + JSON.stringify(data, null, 2)) console.log('```\n') - console.log('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) - console.log('\n# ---- Response -----\n\n' + yaml.stringify(data)) - console.log('```\n') }) } } From e9ec5e24fa2d8128265245657046aa84bc2788fa Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 13:27:03 +0100 Subject: [PATCH 031/221] fix typos --- c/src/api/eth1/rpc_api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index a1e1324a4..64cf4af97 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -432,10 +432,10 @@ static in3_ret_t in3_ecrecover(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_sign_data(in3_rpc_handle_ctx_t* ctx) { - const is_eth_sign = strcmp(ctx->method, "eth_sign") == 0; - bytes_t data = d_to_bytes(d_get_at(ctx->params, is_eth_sign ? 1 : 0)); - const bytes_t* pk = d_get_bytes_at(ctx->params, is_eth_sign ? 0 : 1); - char* sig_type = d_get_string_at(ctx->params, 2); + const bool is_eth_sign = strcmp(ctx->method, "eth_sign") == 0; + bytes_t data = d_to_bytes(d_get_at(ctx->params, is_eth_sign ? 1 : 0)); + const bytes_t* pk = d_get_bytes_at(ctx->params, is_eth_sign ? 0 : 1); + char* sig_type = d_get_string_at(ctx->params, 2); if (!sig_type) sig_type = is_eth_sign ? "eth_sign" : "raw"; // if (!pk) return req_set_error(ctx, "Invalid sprivate key! must be 32 bytes long", IN3_EINVAL); @@ -547,14 +547,14 @@ static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { - CHECK_PARAMS_LEN(ctx->req, ctx->parmas, 1) + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) d_token_t* tx_data = ctx->params + 1; bytes_t tx_raw = bytes(NULL, 0); bytes_t* from_b = NULL; bytes_t* data = NULL; - if (strcmp(ctx->method,"eth_signTransaction")==0 || d_type(tx_data)==T_OBJECT { - TRY(eth_prepare_unsigned_tx(tx_data,ctx->req,&tx_raw))) - from_b = d_get_bytes(tx_data,K_FROM); + if (strcmp(ctx->method, "eth_signTransaction") == 0 || d_type(tx_data) == T_OBJECT) { + TRY(eth_prepare_unsigned_tx(tx_data, ctx->req, &tx_raw)) + from_b = d_get_bytes(tx_data, K_FROM); data = &tx_raw; } else { From 6e8658a34a247f103a1ee7f92c45cb6a396c2d1e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 13:27:24 +0100 Subject: [PATCH 032/221] update _in3.sh per script --- scripts/_in3.sh | 137 +++++++++++++++++++++----------------- scripts/_in3.template | 109 ++++++++++++++++++++++++++++++ scripts/build_rpc_docu.js | 19 +++++- 3 files changed, 202 insertions(+), 63 deletions(-) create mode 100755 scripts/_in3.template diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 4b9a90401..e70386153 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -2,71 +2,86 @@ local -a subcmds args sig_in3 sig_erc20 sig_ms subcmds=( - 'eth_blockNumber:last block number' - 'eth_getBlockByNumber: get block data ' - 'eth_getTransactionByHash: get the transaction ' - 'eth_getTransactionByBlockHashAndIndex: get the transaction ' - 'eth_getTransactionByBlockNumberAndIndex: get the transaction ' - 'eth_getTransactionReceipt: get the transaction receipt ' - 'eth_getLogs: get the events ' - 'eth_getBlockByHash: get block data ' - 'eth_getCode: get code of a contract
' - 'eth_getBalance: get balance of address
' - 'web3_clientVersion: returns the client version' - 'web3_sha3: hashes the gives data ' - 'net_version: eth version' - 'eth_protocolVersion: RPC-Spec Version' - 'eth_gasPrice: average gas price used in the last blocks' - 'eth_getStorageAt: storage value of an contract
' - 'eth_getTransactionCount: nonce of the account
' - 'eth_getBlockTransactionCountByHash: Number of Transaction in the Block ' - 'eth_getBlockTransactionCountByNumber: Number of Transaction in the Block ' - 'eth_sendTransaction: sends a transaction ' - 'eth_sendRawTransaction: sends a signed transaction ' - 'eth_call: calls a function of a contract ' - 'eth_estimateGas: estimates the gas for a call a contract ' - 'in3_nodeList: shows the nodeList' - 'in3_weights: shows the weights of nodeList' - 'in3_cacheClear: clears the cache' - 'in3_sign: requests a node to sign. ' - 'in3_ens: resolve ens-name. ' - 'ipfs_get: requests and verifies the content for a given ipfs-hash and write the content to stdout ' - 'ipfs_put: reads data from stdin and pushes to the ipfs-network. it write the ipfs-hash to stdout.' 'send: sends a transaction ...args' 'call: calls a contract ...args' 'abi_encode: encodes the arguments as described in the method signature using ABI-Encoding. ...args' 'abi_decode: decodes the data based on the signature.. ' - 'pk2address: extracts the public address from a private key ' - 'pk2public: extracts the public key from a private key ' - 'ecrecover: extracts the address and public key from a signature ' - 'key: reads the private key from JSON-Keystore file and returns the private key. ' - 'createkey: generates a random key' - 'in3_checksumAddress: display the address as checksumAddress' - 'keccak: calculate the keccak hash of the ' - 'in3_toWei: returns the amount of wei of the value passed as float of eth.' - 'in3_signData: signs the as passed as argument with the configured signer. optional ' - 'in3_cacheClear: clears the local filecache' - 'in3_signTx: signs a raw transaction ' - 'zksync_deposit: sends a L1-Transaction to add to the deposit ' - 'zksync_transfer: transfers the given amount from the configured account to another account in L2 ' - 'zksync_withdraw: transfers the given amount from the configured account in L2 to another account in L1 ' - 'zksync_set_key: sets the configured key as signer for the account args: ' - 'zksync_emergency_withdraw: sends a L1 Tx to withdraw all tokens from L2 ' - 'zksync_sync_key: calculates and returns the pk used to sign zksync-tx (using babyjupjup curve)' - 'zksync_aggregate_pubkey: calculates the combined musig public key for the concatinated public keys (each with 32 bytes)' - 'zksync_pubkeyhash: returns the pubkeyhash of the signer based on the config' - 'zksync_pubkey: returns the compact pubkey(32 bytes) of the signer based on the config or from the , if given' - 'zksync_account_address: returns address of the zksync-account based on the config' - 'zksync_account_info: returns the current balance and state of the account' - 'zksync_tokens: returns a list of all available tokens' - 'zksync_sign: sign the given with the syncKey. If the -zms and -zmu are passed, it will use musig schnirr sigs to create MPC-Signature' - 'zksync_verify: verifies the signature of the ' - 'iamo_add_user: adds a new user to the vault-api' - 'iamo_zk_add_wallet: add a json-definition of a mutisig.' - 'iamo_zk_create_wallet: creates a multisig-definition based on the Approver-API (-zmu) ....' - 'iamo_zk_get_config: returns the configured master copy, codehash and creator for creating create2-accounts' - 'iamo_zk_create_signatures: creates a array of signatures to reach the threshold of a multisig based on and ' - 'iamo_zk_verify_signatures: verfies signatures to reach the threshold of a multisig based on and ' + 'getbestblockhash: Returns the hash of the best (tip) block in the longest blockchain' + 'getblock: Returns data of block for given block hash ' + 'getblockcount: Returns the number of blocks in the longest blockchain' + 'getblockheader: Returns data of block header for given block hash ' + 'getdifficulty: Returns the proof-of-work difficulty as a multiple of the minimum difficulty ' + 'getrawtransaction: Returns the raw transaction data ' + 'in3_proofTarget: Whenever the client is not able to trust the changes of the target (which is the case if a block can... ' + 'eth_blockNumber: returns the number of the most recent block' + 'eth_call: calls a function of a contract (or simply executes the evm opcodes) and returns the result ' + 'eth_estimateGas: calculates the gas needed to execute a transaction ' + 'eth_getBalance: gets the balance of an account for a given block ' + 'eth_getBlockByHash: Returns information about a block by hash ' + 'eth_getBlockByNumber: returns information about a block by block number ' + 'eth_getBlockTransactionCountByHash: returns the number of transactions ' + 'eth_getBlockTransactionCountByNumber: returns the number of transactions ' + 'eth_getCode: gets the code of a given contract ' + 'eth_getLogs: searches for events matching the given criteria ' + 'eth_getStorageAt: gets the storage value of a given key ' + 'eth_getTransactionByBlockHashAndIndex: returns the transaction data ' + 'eth_getTransactionByBlockNumberAndIndex: returns the transaction data ' + 'eth_getTransactionByHash: returns the transaction data ' + 'eth_getTransactionCount: gets the nonce or number of transaction sent from this account at a given block ' + 'eth_getTransactionReceipt: The Receipt of a Transaction ' + 'eth_getUncleCountByBlockHash: returns the number of uncles ' + 'eth_getUncleCountByBlockNumber: returns the number of uncles ' + 'eth_sendRawTransaction: sends or broadcasts a prviously signed raw transaction ' + 'eth_sendTransaction: signs and sends a Transaction ' + 'eth_sendTransactionAndWait: signs and sends a Transaction, but then waits until the transaction receipt can be verified ' + 'eth_sign: The sign method calculates an Ethereum specific signature with: ' + 'eth_signTransaction: Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTrans... ' + 'keccak: Returns Keccak-256 (not the standardized SHA3-256) of the given data' + 'net_version: the Network Version (currently 1)' + 'sha256: Returns sha-256 of the given data ' + 'web3_clientVersion: Returns the underlying client version' + 'web3_sha3: Returns Keccak-256 (not the standardized SHA3-256) of the given data ' + 'eth_accounts: returns a array of account-addresss the incubed client is able to sign with' + 'in3_abiDecode: based on the ' + 'in3_abiEncode: based on the ' + 'in3_addRawKey: adds a raw private key as signer, which allows signing transactions ' + 'in3_cacheClear: clears the incubed cache (usually found in the ' + 'in3_checksumAddress: Will convert an upper or lowercase Ethereum address to a checksum address
' + 'in3_config: changes the configuration of a client ' + 'in3_decryptKey: decrypts a JSON Keystore file as defined in the ' + 'in3_ecrecover: extracts the public key and address from signature ' + 'in3_ens: resolves a ens-name ' + 'in3_fromWei: converts a given uint (also as hex) with a wei-value into a specified unit ' + 'in3_nodeList: fetches and verifies the nodeList from a node ' + 'in3_pk2address: extracts the address from a private key ' + 'in3_pk2public: extracts the public key from a private key ' + 'in3_prepareTx: prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction ' + 'in3_sign: requests a signed blockhash from the node ' + 'in3_signData: signs the given data ' + 'in3_signTx: signs the given raw Tx (as prepared by in3_prepareTx ) ' + 'in3_toWei: converts the given value into wei ' + 'in3_whitelist: Returns whitelisted in3-nodes addresses
' + 'ipfs_get: Fetches the data for a requested ipfs-hash ' + 'ipfs_put: Stores ipfs-content to the ipfs network ' + 'zksync_account_address: returns the address of the account used' + 'zksync_account_info: returns account_info from the server
' + 'zksync_aggregate_pubkey: calculate the public key based on multiple public keys signing together using schnorr musig signatur... ' + 'zksync_contract_address: returns the contract address' + 'zksync_deposit: sends a deposit-transaction and returns the opId, which can be used to tradck progress ' + 'zksync_emergency_withdraw: withdraws all tokens for the specified token as a onchain-transaction ' + 'zksync_ethop_info: returns the state or receipt of the the PriorityOperation ' + 'zksync_get_token_price: returns current token-price ' + 'zksync_get_tx_fee: calculates the fees for a transaction
' + 'zksync_pubkey: returns the current packed PubKey based on the config set' + 'zksync_pubkeyhash: returns the current PubKeyHash based on the configuration set ' + 'zksync_set_key: sets the signerkey based on the current pk or as configured in the config ' + 'zksync_sign: returns the schnorr musig signature based on the current config ' + 'zksync_sync_key: returns private key used for signing zksync-transactions' + 'zksync_tokens: returns the list of all available tokens' + 'zksync_transfer: sends a zksync-transaction and returns data including the transactionHash ' + 'zksync_tx_info: returns the state or receipt of the the zksync-tx ' + 'zksync_verify: returns 0 or 1 depending on the successfull verification of the signature ' + 'zksync_withdraw: withdraws the amount to the given `ethAddress` for the given token ' ) args=( diff --git a/scripts/_in3.template b/scripts/_in3.template new file mode 100755 index 000000000..6a68a366c --- /dev/null +++ b/scripts/_in3.template @@ -0,0 +1,109 @@ +#compdef in3 + +local -a subcmds args sig_in3 sig_erc20 sig_ms +subcmds=( + 'send: sends a transaction ...args' + 'call: calls a contract ...args' + 'abi_encode: encodes the arguments as described in the method signature using ABI-Encoding. ...args' + 'abi_decode: decodes the data based on the signature.. ' +$CMDS + ) + +args=( + '-c[chain]:chain id:(mainnet goerli ewc ipfs btc local)' + '-st[the type of the signature data]:st:(eth_sign raw hash)' + '-p[the Verification level]:p:(none standard full)' + '-pwd[password to unlock the key]:pwd:()' + '-np[short for -p none]' + '-ns[short for no stats, which does count this request in the public stats]' + '-eth[onverts the result (as wei) to ether]' + '-l[replaces "latest" with latest BlockNumber - the number of blocks given]:latest:(1 2 3 4 5 6 7 8 9 10)' + '-s[number of signatures to use when verifying]:sigs:(1 2 3 4 5 6 7 8 9 10)' + '-port[if specified it will run as http-server listening to the given port]:port:(8545)' + '-am[Allowed Methods when used with -port as comma seperated list of methods]:allowed_methods:()' + '-b[the blocknumber to use when making calls]:b:(latest earliest 0x)' + '-to[the target address of the call or send]:to:(0x)' + '-d[the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin]:date:()' + '-gas[the gas limit to use when sending transactions]:gas:(21000 100000 250000 500000 1000000 2000000)' + '-gas_price[the gas price to use within a tx]:gas_price:()' + '-pk[the private key as raw or path to the keystorefile]:pk:()' + '-k[the private key to sign request for incetives payments]:k:()' + '-help[displays this help message]' + '-tr[runs test request when showing in3_weights]' + '-thr[runs test request including health-check when showing in3_weights]' + '-ms[address of a imao multisig to redirect all tx through]:ms:()' + '-version[displays the version]' + '-debug[if given incubed will output debug information when executing]' + '-value[the value to send when sending a transaction. (hexvalue or float/integer with the suffix eth]:value:(1.0eth)' + '-w[instead returning the transaction, it will wait until the transaction is mined and return the transactionreceipt]' + '-md[specifies the minimum Deposit of a node in order to be selected as a signer]' + '-json[the result will be returned as json]' + '-hex[the result will be returned as hex]' + '-kin3[the response including in3-section is returned]' + '-q[quiet no debug output]' + '-os[only sign, do not send the raw Transaction]' + '-ri[read response from stdin]' + '-ro[write raw response to stdout]' + '-a[max number of attempts before giving up (default 5)]:attempts:(1 2 3 4 5 6 7 8 9)' + '-rc[number of request per try (default 1)]:requestCount:(1 2 3 4 5 6 7 8 9)' + '-fi[read recorded request from file]:fi:()' + '-fo[recorded request and write to file]:fo:()' + '-nl[a comma seperated list of urls as address:url to be used as fixed nodelist]:nl:()' + '-bn[a comma seperated list of urls as address:url to be used as boot nodes]:bn:()' + '-zks[URL of the zksync-server]:zks:(https\://api.zksync.io/jsrpc http\://localhost\:3030)' + '-zkss[zksync signatures to pass along when signing]:zkss:()' + '-zka[zksync account to use]:zka:()' + '-zkat[zksync account type]:zkat:(pk contract create2)' + '-zsk[zksync signer seed - if not set this key will be derrived from account unless create2]:zsk:()' + '-zc2[zksync create2 arguments in the form ::. if set the account type is also changed to create2]:zc2:()' + '-zms[public keys of a musig schnorr signatures to sign with]:zms:()' + '-zmu[url for signing service matching the first remote public key]:zmu:(http\://localhost\:8080)' + '-zvpm[method for calling to verify the proof in server mode]:zvpm:(iamo_zksync_verify_signatures)' + '-zcpm[method for calling to create the proof]:zcpm:(iamo_zksync_create_signatures)' + '-idk[iamo device key]:idk:()' + '-imc[the master copy address to be used]:imc:()' + '-if[iamo factory address]:if:()' + + ':method:{_describe command subcmds}' + ':arg1:{_describe command sig_in3 -- sig_erc20 -- sig_ms}' +) + +sig_in3=( + 'minDeposi()\:uint: minimal deposit' + 'adminKey()\:address: admin key' + 'nodeRegistryData()\:address:addres of the data contract' + 'supportedToken()\:address: supported token' + 'totalNodes()\:uint: number of nodes' + 'blockRegistry()\:address: BlockHashRegistry' + 'nodes(uint256)\:(string,uint256,uint64,uint192,uint64,address,bytes32): node data' + 'unregisteringNode(address):unregister a node' + 'updateNode(address,string,uint192,uint64,uint256): update nod properties' + 'transferOwnership(address,address): transfers ownership from signer to new owner', + 'registerNode(string,uint192,uint64,uint256): registers a Node' + 'snapshot(): creates a snapshot for the current block' +) +sig_erc20=( + 'balanceOf(address)\:uint:getting the balance of' + 'name()\:string:token name' + 'totalSupply()\:uint:total Balance' + 'transfer(address,uint256):transfer tokens' + 'transferFrom(address,address,uint256):transfer from to account tokens' + 'approve(address,uint256):approve the amount for the given address' + 'allowance(address,address)\:uint: the approved amount' +) +sig_ms=( + 'getOwners()\:(address[]): multisig' + 'getMessageHash(bytes)\:bytes: gets the message hash of a transaction' + 'isOwner(address)\:bool:is owner' + 'signedMessages(bytes32)\:uint: number of signed messages' + 'approvedHashes(address,bytes32)\:uint:check if the hash was approved' + 'nonce()\:uint:the nonce of the multisig' + 'getModules()\:address[]:List of modules' + 'getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)\:bytes32:calculates the transaction hash' + 'getThreshold()\:uint' + 'addOwnerWithThreshold(address,uint256):adds an owner with the given threshold' + 'changeThreshold(uint256): changes the threshold' + 'execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes): executes a transaction' +) + +_arguments -C $args diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 44ccd206f..af74eca0c 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -48,7 +48,8 @@ scan('../c/src') docs.in3.in3_config.params.config.type = config console.log('# API RPC\n\n') console.log('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') - +const zsh_complete = fs.readFileSync('_in3.template', 'utf8') +let zsh_cmds = [] for (const s of Object.keys(docs).sort()) { const rpcs = docs[s] console.log("## " + s + "\n\n") @@ -56,13 +57,23 @@ for (const s of Object.keys(docs).sort()) { delete rpcs.descr for (const rpc of Object.keys(rpcs).sort()) { const def = rpcs[rpc] + let z = " '" + rpc + ': ' + let zd = (def.descr || (def.alias && rpcs[def.alias].descr) || '').trim() + if (zd.indexOf('.') >= 0) zd = zd.substr(0, zd.indexOf('.')) + if (zd.indexOf('\n') >= 0) zd = zd.substr(0, zd.indexOf('\n')) + if (zd.indexOf('[') >= 0) zd = zd.substr(0, zd.indexOf('[')) + if (zd.length > 100) zd = zd.substr(0, 100) + '...' + z += zd + console.log('### ' + rpc + '\n\n') asArray(def.alias).forEach(_ => console.log(rpc + ' is just an alias for ' + link(_) + '.See Details there.\n\n')) - if (def.descr) console.log(def.descr + '\n') + if (def.descr) + console.log(def.descr + '\n') if (def.params) { console.log("*Parameters:*\n") print_object(def.params, '', true) console.log() + z += ' ' + Object.keys(def.params).map(_ => '<' + _ + '>').join(' ') } else if (!def.alias) console.log("*Parameters:* - \n") @@ -125,7 +136,11 @@ for (const s of Object.keys(docs).sort()) { console.log('```\n') }) + z += "'" + zsh_cmds.push(z) } } +fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')), { encoding: 'utf8' }) + From d53c8e501ab953990791987c4ec6efe067bc0d02 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 13:51:26 +0100 Subject: [PATCH 033/221] add documented only --- scripts/check_bindings.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 10c000d0b..87cb997ac 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -21,7 +21,7 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => }, []) const check = (val, c) => val ? ((++res[c]) && ' \u2705 ') : ' \u274c ' const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0, autocompl: 0 } -const doc_rpc = grep('\"### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()).map(_ => _ === 'proofTarget' ? 'btc_proofTarget' : _) +const doc_rpc = grep('\"^### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()) const java_rpc = strings('../java/src', '"') const wasm_rpc = strings('../wasm/src', '\'') const python_rpc = strings('../python/in3', '"') @@ -30,6 +30,7 @@ const dotnet_rpc = strings('../dotnet/In3', '"', '*.cs') const c_api = strings('../c/src/api', '"',) const autocomplete = grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]) const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) +doc_rpc.filter(_ => all_rpc_names.indexOf(_) == -1).forEach(_ => all_rpc_names.push(_ + '*')) all_rpc_names.sort() console.log('RPC-Method'.padEnd(40) + ' doc wasm java python rust dotnet c_api autocmpl') console.log('-'.padEnd(44 + 7 * 8, '-')) @@ -37,7 +38,7 @@ console.log('-'.padEnd(44 + 7 * 8, '-')) all_rpc_names.forEach(rpc => console.log(rpc.padEnd(40) + ' : ' - + check(doc_rpc.indexOf(rpc) != -1, 'doc') + + check(doc_rpc.indexOf((rpc = rpc.replace('*', ''))) != -1, 'doc') + check(wasm_rpc.indexOf(rpc) != -1, 'wasm') + check(java_rpc.indexOf(rpc) != -1, 'java') + check(python_rpc.indexOf(rpc) != -1, 'python') From 1cc5efceebd209a77a702cb56d8759447ff3e2be Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 13:51:42 +0100 Subject: [PATCH 034/221] renamed btc_target --- c/src/verifier/btc/btc.c | 2 +- c/src/verifier/btc/rpc.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/verifier/btc/btc.c b/c/src/verifier/btc/btc.c index 3c5577c27..59020e5fb 100644 --- a/c/src/verifier/btc/btc.c +++ b/c/src/verifier/btc/btc.c @@ -465,7 +465,7 @@ static in3_ret_t in3_verify_btc(btc_target_conf_t* conf, in3_vctx_t* vc) { hex_to_bytes(d_string(block_hash), 64, hash, 32); return btc_verify_block(conf, vc, hash, d_len(params) > 1 ? d_get_int_at(params, 1) : 1, false); } - if (strcmp(vc->method, "btc_proofTarget") == 0) { // we use strcmp directly here, because btc_proofTarget is an internal rpc-call, which does not have to be part of any API. + if (VERIFY_RPC("btc_proofTarget")) { REQUIRE_EXPERIMENTAL(vc->req, "btc") return btc_verify_target_proof(conf, vc, params); } diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index f90a3d18a..894ca4175 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -619,7 +619,7 @@ btc: cbtx: "0x02000000000101000000000000000000000000000000000000000...000000" cbtxMerkleProof: "0xa3d607b274770911e53f06dbdb76440580ff968239...0ba297" - in3_proofTarget: + btc_proofTarget: descr: Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. params: target_dap: From 5d0d9616c6a578aca73a1e1731313e026afb44ea Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 25 Mar 2021 15:18:08 +0100 Subject: [PATCH 035/221] optimize check_bindings --- scripts/_in3.sh | 2 +- scripts/check_bindings.js | 52 ++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/scripts/_in3.sh b/scripts/_in3.sh index e70386153..25be8ff50 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -6,13 +6,13 @@ subcmds=( 'call: calls a contract ...args' 'abi_encode: encodes the arguments as described in the method signature using ABI-Encoding. ...args' 'abi_decode: decodes the data based on the signature.. ' + 'btc_proofTarget: Whenever the client is not able to trust the changes of the target (which is the case if a block can... ' 'getbestblockhash: Returns the hash of the best (tip) block in the longest blockchain' 'getblock: Returns data of block for given block hash ' 'getblockcount: Returns the number of blocks in the longest blockchain' 'getblockheader: Returns data of block header for given block hash ' 'getdifficulty: Returns the proof-of-work difficulty as a multiple of the minimum difficulty ' 'getrawtransaction: Returns the raw transaction data ' - 'in3_proofTarget: Whenever the client is not able to trust the changes of the target (which is the case if a block can... ' 'eth_blockNumber: returns the number of the most recent block' 'eth_call: calls a function of a contract (or simply executes the evm opcodes) and returns the result ' 'eth_estimateGas: calculates the gas needed to execute a transaction ' diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 87cb997ac..95c87adc4 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -19,35 +19,37 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => } return p }, []) -const check = (val, c) => val ? ((++res[c]) && ' \u2705 ') : ' \u274c ' -const res = { doc: 0, java: 0, wasm: 0, python: 0, rust: 0, dotnet: 0, c: 0, autocompl: 0 } -const doc_rpc = grep('\"^### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()) -const java_rpc = strings('../java/src', '"') -const wasm_rpc = strings('../wasm/src', '\'') -const python_rpc = strings('../python/in3', '"') -const rust_rpc = strings('../rust/in3-rs/src', '"') -const dotnet_rpc = strings('../dotnet/In3', '"', '*.cs') -const c_api = strings('../c/src/api', '"',) -const autocomplete = grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]) +const label = (n, l) => l ? ('\033[' + l + 'm' + n.replace('*', '') + '\033[0m') : n +const is_allowed = ['btc_proofTarget'] +const check = (list, name, c) => list.indexOf(name) != -1 ? ((++res[c]) && ' \u2705 ') : (is_allowed.indexOf(name) == -1 ? ' \u274c ' : ((++res[c]) && ' \u274e ')) +const bindings = { + doc: grep('\"^### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()), + java: strings('../java/src', '"'), + wasm: strings('../wasm/src', '\''), + python: strings('../python/in3', '"'), + rust: strings('../rust/in3-rs/src', '"'), + dotnet: strings('../dotnet/In3', '"', '*.cs'), + c_api: strings('../c/src/api', '"',), + autocmpl: grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]), +} +const res = Object.keys(bindings).reduce((p, c) => ({ ...p, [c]: 0 }), {}) const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) -doc_rpc.filter(_ => all_rpc_names.indexOf(_) == -1).forEach(_ => all_rpc_names.push(_ + '*')) +bindings.doc.filter(_ => all_rpc_names.indexOf(_) == -1).forEach(_ => all_rpc_names.push(_ + '*')) all_rpc_names.sort() -console.log('RPC-Method'.padEnd(40) + ' doc wasm java python rust dotnet c_api autocmpl') -console.log('-'.padEnd(44 + 7 * 8, '-')) +console.log('RPC-Method'.padEnd(40) + ' ' + Object.keys(bindings).map(_ => _.padEnd(7)).join('')) +console.log('-'.padEnd(45 + 7 * Object.keys(bindings).length, '-')) -all_rpc_names.forEach(rpc => - console.log(rpc.padEnd(40) + ' : ' - + check(doc_rpc.indexOf((rpc = rpc.replace('*', ''))) != -1, 'doc') - + check(wasm_rpc.indexOf(rpc) != -1, 'wasm') - + check(java_rpc.indexOf(rpc) != -1, 'java') - + check(python_rpc.indexOf(rpc) != -1, 'python') - + check(rust_rpc.indexOf(rpc) != -1, 'rust') - + check(dotnet_rpc.indexOf(rpc) != -1, 'dotnet') - + check(c_api.indexOf(rpc) != -1, 'c') - + check(autocomplete.indexOf(rpc) != -1, 'autocompl') - ) -) +all_rpc_names.forEach(rpc => { + let s = '', c = 0, l = rpc.replace('*', '') + Object.keys(bindings).forEach(k => { + c -= res[k] + s += check(bindings[k], l, k) + c += res[k] + }) + console.log(label(l.padEnd(40), rpc.endsWith('*') ? '31' : (Object.keys(bindings).length == c ? '32' : '33')) + ' : ' + s) +}) + console.log("\nSummary:") Object.keys(res).forEach(k => console.log(k.padEnd(8) + ': ' + (res[k] * 100 / all_rpc_names.length).toFixed(0) + ' % ')) From e268044937bc9a29a8039135de4923be4493c21d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 27 Mar 2021 22:09:43 +0100 Subject: [PATCH 036/221] add auto config --- c/src/cmd/in3/main.c | 53 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 1368e97d4..b8f4d3b3e 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -252,6 +252,53 @@ void read_pass(char* pw, int pwsize) { recorder_print(1, COLORT_RESETHIDDEN); //reveal typing } +static bool configure_arg(in3_t* c, char* arg, int* i, int argc) { + UNUSED_VAR(i); + UNUSED_VAR(argc); + char* value = strchr(arg, '='); + char* name = NULL; + if (!value) { + // die("invalid syntax for --key=value"); + value = "true"; + name = alloca(strlen(arg) + 1); + strcpy(name, arg); + } + else { + value++; + name = alloca(value - arg); + strncpy(name, arg, value - arg - 1); + name[value - arg - 1] = 0; + } + if (name[0] == '-' && name[1] == '-') { + name += 2; + char* p = strtok(name, "."); + sb_t sb = {0}; + sb_add_char(&sb, '{'); + int b = 1; + while (p) { + char* next = strtok(NULL, "."); + if (!next) { + if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) + sb_print(&sb, "\"%s\":", p, value); + else + sb_print(&sb, "\"%s\":\"%s\"", p, value); + break; + } + b++; + sb_print(&sb, "\"%s\":{", p); + p = next; + continue; + } + for (; b; b--) sb_add_char(&sb, '}'); + in3_log_info("configure %s \n", sb.data); + char* error = in3_configure(c, sb.data); + if (error) + die(error); + return true; + } + return false; +} + // accepts a value as // 0.1eth // 2keth @@ -981,15 +1028,15 @@ int main(int argc, char* argv[]) { i++; } // now handle arguments for special methods + else if (configure_arg(c, argv[i], &i, argc)) + continue; else { if (method == NULL) method = argv[i]; else if (strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0) pk_file = argv[i]; - else if (strcmp(method, "sign") == 0 && !data) { - + else if (strcmp(method, "sign") == 0 && !data) data = b_new((uint8_t*) argv[i], strlen(argv[i])); - } else if (sig == NULL && (strcmp(method, "call") == 0 || strcmp(method, "send") == 0 || strcmp(method, "abi_encode") == 0 || strcmp(method, "abi_decode") == 0)) sig = argv[i]; else { From 4de67532a44a3662d30b8d7063aa0da86fb6dd8c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 28 Mar 2021 23:13:57 +0200 Subject: [PATCH 037/221] fix wasm --- c/src/api/eth1/rpc_api.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 64cf4af97..33a12dd98 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -553,9 +553,13 @@ static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { bytes_t* from_b = NULL; bytes_t* data = NULL; if (strcmp(ctx->method, "eth_signTransaction") == 0 || d_type(tx_data) == T_OBJECT) { +#if defined(ETH_BASIC) TRY(eth_prepare_unsigned_tx(tx_data, ctx->req, &tx_raw)) from_b = d_get_bytes(tx_data, K_FROM); data = &tx_raw; +#else + return req_set_error(ctx->req, "eth_basic is needed in order to use eth_prepareTx", IN3_EINVAL); +#endif } else { data = d_get_bytes_at(ctx->params, 0); From a3441959d532935e0ecf164026c77c9255599374 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 29 Mar 2021 11:20:36 +0200 Subject: [PATCH 038/221] add CONFIG_KEY for checking --- c/src/core/client/client_init.c | 38 ++++++++--------- c/src/core/util/debug.h | 1 + c/src/nodeselect/full/nodeselect_def.c | 58 +++++++++++++------------- c/src/pay/zksync/zksync.c | 36 ++++++++-------- c/src/signer/pk-signer/signer.c | 4 +- c/src/verifier/btc/btc.c | 4 +- scripts/check_bindings.js | 36 +++++++++++++++- 7 files changed, 106 insertions(+), 71 deletions(-) diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c index 6d7bc8329..bc66dad66 100644 --- a/c/src/core/client/client_init.c +++ b/c/src/core/client/client_init.c @@ -245,18 +245,18 @@ char* in3_configure(in3_t* c, const char* config) { for (d_iterator_t iter = d_iter(json->result); iter.left; d_iter_next(&iter)) { d_token_t* token = iter.token; - if (token->key == key("autoUpdateList")) { + if (token->key == CONFIG_KEY("autoUpdateList")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_AUTO_UPDATE_LIST, (d_int(token) ? true : false)); } - else if (token->key == key("chainType")) + else if (token->key == CONFIG_KEY("chainType")) ; // Ignore - handled within `chainId` case - else if (token->key == key("chainId")) { + else if (token->key == CONFIG_KEY("chainId")) { EXPECT_TOK(token, IS_D_UINT32(token) || (d_type(token) == T_STRING && chain_id(token) != 0), "expected uint32 or string value (mainnet/goerli)"); // check if chainType is set int ct_ = -1; - d_token_t* ct_token = d_get(json->result, key("chainType")); + d_token_t* ct_token = d_get(json->result, CONFIG_KEY("chainType")); if (ct_token) { ct_ = chain_type(ct_token); EXPECT_TOK(ct_token, ct_ != -1, "expected (btc|eth|ipfs|)"); @@ -270,11 +270,11 @@ char* in3_configure(in3_t* c, const char* config) { in3_client_register_chain(c, c->chain.chain_id, c->chain.type, 2); if (changed) in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); } - else if (token->key == key("signatureCount")) { + else if (token->key == CONFIG_KEY("signatureCount")) { EXPECT_TOK_U8(token); c->signature_count = (uint8_t) d_int(token); } - else if (token->key == key("finality")) { + else if (token->key == CONFIG_KEY("finality")) { EXPECT_TOK_U16(token); #ifdef POA if (c->chain.chain_id == CHAIN_ID_GOERLI) @@ -282,24 +282,24 @@ char* in3_configure(in3_t* c, const char* config) { #endif c->finality = (uint16_t) d_int(token); } - else if (token->key == key("includeCode")) { + else if (token->key == CONFIG_KEY("includeCode")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_INCLUDE_CODE, (d_int(token) ? true : false)); } - else if (token->key == key("bootWeights")) { + else if (token->key == CONFIG_KEY("bootWeights")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_BOOT_WEIGHTS, (d_int(token) ? true : false)); } - else if (token->key == key("maxAttempts")) { + else if (token->key == CONFIG_KEY("maxAttempts")) { EXPECT_TOK_U16(token); EXPECT_CFG(d_int(token), "maxAttempts must be at least 1"); c->max_attempts = d_int(token); } - else if (token->key == key("keepIn3")) { + else if (token->key == CONFIG_KEY("keepIn3")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_KEEP_IN3, (d_int(token) ? true : false)); } - else if (token->key == key("debug")) { + else if (token->key == CONFIG_KEY("debug")) { if (d_int(token)) { in3_log_set_level(LOG_TRACE); in3_log_set_quiet(false); @@ -307,23 +307,23 @@ char* in3_configure(in3_t* c, const char* config) { else in3_log_set_quiet(true); } - else if (token->key == key("stats")) { + else if (token->key == CONFIG_KEY("stats")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_STATS, (d_int(token) ? true : false)); } - else if (token->key == key("useBinary")) { + else if (token->key == CONFIG_KEY("useBinary")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_BINARY, (d_int(token) ? true : false)); } - else if (token->key == key("experimental")) { + else if (token->key == CONFIG_KEY("experimental")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_ALLOW_EXPERIMENTAL, (d_int(token) ? true : false)); } - else if (token->key == key("useHttp")) { + else if (token->key == CONFIG_KEY("useHttp")) { EXPECT_TOK_BOOL(token); BITMASK_SET_BOOL(c->flags, FLAGS_HTTP, (d_int(token) ? true : false)); } - else if (token->key == key("maxVerifiedHashes")) { + else if (token->key == CONFIG_KEY("maxVerifiedHashes")) { EXPECT_TOK_U16(token); if (c->max_verified_hashes < d_long(token)) { c->chain.verified_hashes = _realloc(c->chain.verified_hashes, @@ -335,18 +335,18 @@ char* in3_configure(in3_t* c, const char* config) { c->max_verified_hashes = d_long(token); c->alloc_verified_hashes = c->max_verified_hashes; } - else if (token->key == key("timeout")) { + else if (token->key == CONFIG_KEY("timeout")) { EXPECT_TOK_U32(token); c->timeout = d_long(token); } - else if (token->key == key("proof")) { + else if (token->key == CONFIG_KEY("proof")) { EXPECT_TOK_STR(token); EXPECT_TOK(token, !strcmp(d_string(token), "full") || !strcmp(d_string(token), "standard") || !strcmp(d_string(token), "none"), "expected values - full/standard/none"); c->proof = strcmp(d_string(token), "full") == 0 ? PROOF_FULL : (strcmp(d_string(token), "standard") == 0 ? PROOF_STANDARD : PROOF_NONE); } - else if (token->key == key("verifiedHashes")) { + else if (token->key == CONFIG_KEY("verifiedHashes")) { EXPECT_TOK_ARR(token); EXPECT_TOK(token, (unsigned) d_len(token) <= c->max_verified_hashes, "expected array len <= maxVerifiedHashes"); if (!c->chain.verified_hashes) diff --git a/c/src/core/util/debug.h b/c/src/core/util/debug.h index 609e21b3b..0ba213e51 100644 --- a/c/src/core/util/debug.h +++ b/c/src/core/util/debug.h @@ -178,4 +178,5 @@ static inline void add_hex(sb_t* sb, char prefix, const char* property, bytes_t if (strcmp(ctx->method, name) == 0) return fn; /** used in if-conditions and returns true if the vc->method mathes the name. It is also used as marker.*/ #define VERIFY_RPC(name) (strcmp(vc->method, name) == 0) +#define CONFIG_KEY(name) key(name) #endif /* DEBUG_H */ \ No newline at end of file diff --git a/c/src/nodeselect/full/nodeselect_def.c b/c/src/nodeselect/full/nodeselect_def.c index abaa49b00..d0923fa6a 100644 --- a/c/src/nodeselect/full/nodeselect_def.c +++ b/c/src/nodeselect/full/nodeselect_def.c @@ -166,7 +166,7 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx json_ctx_t* json = ctx->json; d_token_t* token = ctx->token; - if (token->key == key("preselect_nodes")) { + if (token->key == CONFIG_KEY("preselect_nodes")) { if (data->pre_address_filter) b_free(data->pre_address_filter); if (d_type(token) == T_BYTES && d_len(token) % 20 == 0) data->pre_address_filter = b_dup(d_bytes(token)); @@ -176,30 +176,30 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx EXPECT_CFG(d_type(token) == T_NULL, "invalid preselect_nodes "); } } - else if (token->key == key("replaceLatestBlock")) { + else if (token->key == CONFIG_KEY("replaceLatestBlock")) { EXPECT_TOK_U8(token); ctx->client->replace_latest_block = (uint8_t) d_int(token); const uint64_t dp_ = ctx->client->replace_latest_block; w->node_props = (w->node_props & 0xFFFFFFFF) | (dp_ << 32U); } - else if (token->key == key("requestCount")) { + else if (token->key == CONFIG_KEY("requestCount")) { EXPECT_TOK_U8(token); EXPECT_CFG(d_int(token), "requestCount must be at least 1"); w->request_count = (uint8_t) d_int(token); } - else if (token->key == key("minDeposit")) { + else if (token->key == CONFIG_KEY("minDeposit")) { EXPECT_TOK_U64(token); w->min_deposit = d_long(token); } - else if (token->key == key("nodeProps")) { + else if (token->key == CONFIG_KEY("nodeProps")) { EXPECT_TOK_U64(token); w->node_props = d_long(token); } - else if (token->key == key("nodeLimit")) { + else if (token->key == CONFIG_KEY("nodeLimit")) { EXPECT_TOK_U16(token); w->node_limit = (uint16_t) d_int(token); } - else if (token->key == key("nodeRegistry")) { + else if (token->key == CONFIG_KEY("nodeRegistry")) { EXPECT_TOK_OBJ(token); // this is changing the nodelist config, so we need to make sure we have our own nodelist @@ -219,7 +219,7 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx memcpy(data->registry_id, reg_id.data, 32); } #ifdef NODESELECT_DEF_WL - else if (cp.token->key == key("whiteListContract")) { + else if (cp.token->key == CONFIG_KEY("whiteListContract")) { EXPECT_TOK_ADDR(cp.token); EXPECT_CFG(!has_man_wl, "cannot specify manual whiteList and whiteListContract together!"); has_wlc = true; @@ -228,7 +228,7 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx data->whitelist->needs_update = true; memcpy(data->whitelist->contract, cp.token->data, 20); } - else if (cp.token->key == key("whiteList")) { + else if (cp.token->key == CONFIG_KEY("whiteList")) { EXPECT_TOK_ARR(cp.token); EXPECT_CFG(!has_wlc, "cannot specify manual whiteList and whiteListContract together!"); has_man_wl = true; @@ -250,7 +250,7 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx } } #endif - else if (cp.token->key == key("needsUpdate")) { + else if (cp.token->key == CONFIG_KEY("needsUpdate")) { EXPECT_TOK_BOOL(cp.token); if (!d_int(cp.token)) { if (data->nodelist_upd8_params) { @@ -261,20 +261,20 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx else if (!data->nodelist_upd8_params) data->nodelist_upd8_params = _calloc(1, sizeof(*(data->nodelist_upd8_params))); } - else if (cp.token->key == key("avgBlockTime")) { + else if (cp.token->key == CONFIG_KEY("avgBlockTime")) { EXPECT_TOK_U16(cp.token); data->avg_block_time = (uint16_t) d_int(cp.token); } - else if (cp.token->key == key("nodeList")) { + else if (cp.token->key == CONFIG_KEY("nodeList")) { EXPECT_TOK_ARR(cp.token); if (clear_nodes(data) < 0) goto cleanup; for (d_iterator_t n = d_iter(cp.token); n.left; d_iter_next(&n)) { - EXPECT_CFG(d_get(n.token, key("url")) && d_get(n.token, key("address")), "expected URL & address"); - EXPECT_TOK_STR(d_get(n.token, key("url"))); - EXPECT_TOK_ADDR(d_get(n.token, key("address"))); - EXPECT_CFG(add_node(data, d_get_string(n.token, key("url")), - d_get_longd(n.token, key("props"), 65535), - d_get_byteskl(n.token, key("address"), 20)->data) == IN3_OK, + EXPECT_CFG(d_get(n.token, CONFIG_KEY("url")) && d_get(n.token, CONFIG_KEY("address")), "expected URL & address"); + EXPECT_TOK_STR(d_get(n.token, CONFIG_KEY("url"))); + EXPECT_TOK_ADDR(d_get(n.token, CONFIG_KEY("address"))); + EXPECT_CFG(add_node(data, d_get_string(n.token, CONFIG_KEY("url")), + d_get_longd(n.token, CONFIG_KEY("props"), 65535), + d_get_byteskl(n.token, CONFIG_KEY("address"), 20)->data) == IN3_OK, "add node failed"); assert(data->nodelist_length > 0); BIT_SET(data->nodelist[data->nodelist_length - 1].attrs, ATTR_BOOT_NODE); @@ -288,21 +288,23 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx if (!nodeselect_def_cfg_data(ctx->client->chain.chain_id).data) EXPECT_CFG(!memiszero(data->registry_id, 32) && !memiszero(data->contract, 20), "missing registryId/contract!"); } - else if (token->key == key("rpc")) { + else if (token->key == CONFIG_KEY("rpc")) { EXPECT_TOK_STR(token); TRY(nodelist_seperate_from_registry(&data, w)) - in3_t* c = ctx->client; - c->proof = PROOF_NONE; - c->chain.chain_id = CHAIN_ID_LOCAL; - w->request_count = 1; + in3_t* c = ctx->client; + c->proof = PROOF_NONE; + c->signature_count = 0; + c->chain.chain_id = CHAIN_ID_LOCAL; + w->request_count = 1; clear_nodes(data); - data->nodelist = _calloc(1, sizeof(in3_node_t)); - data->nodelist_length++; - in3_node_t* n = &data->nodelist[0]; - if (n->url) _free(n->url); - n->url = _strdupn(d_string(token), -1); _free(data->nodelist_upd8_params); + data->nodelist_length++; + data->nodelist = _calloc(1, sizeof(in3_node_t)); + data->weights = _calloc(1, sizeof(in3_node_weight_t)); + data->nodelist[0].props = NODE_PROP_DATA; + in3_node_t* n = &data->nodelist[0]; + n->url = _strdupn(d_string(token), -1); data->nodelist_upd8_params = NULL; } else { diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index 5498291a7..1e1edf9a1 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -242,45 +242,45 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { if (ctx->token->key != key("zksync")) return IN3_EIGNORE; // TODO error-reporting for invalid config - const char* provider = d_get_string(ctx->token, key("provider_url")); + const char* provider = d_get_string(ctx->token, CONFIG_KEY("provider_url")); if (provider) { if (conf->provider_url) _free(conf->provider_url); conf->provider_url = _strdupn(provider, -1); } - const char* pvm = d_get_string(ctx->token, key("verify_proof_method")); + const char* pvm = d_get_string(ctx->token, CONFIG_KEY("verify_proof_method")); if (pvm) { if (conf->proof_verify_method) _free(conf->proof_verify_method); conf->proof_verify_method = _strdupn(pvm, -1); } - const char* pcm = d_get_string(ctx->token, key("create_proof_method")); + const char* pcm = d_get_string(ctx->token, CONFIG_KEY("create_proof_method")); if (pcm) { if (conf->proof_create_method) _free(conf->proof_create_method); conf->proof_create_method = _strdupn(pcm, -1); } - bytes_t* account = d_get_bytes(ctx->token, key("account")); + bytes_t* account = d_get_bytes(ctx->token, CONFIG_KEY("account")); if (account && account->len == 20) memcpy(conf->account = _malloc(20), account->data, 20); - bytes_t sync_key = d_to_bytes(d_get(ctx->token, key("sync_key"))); + bytes_t sync_key = d_to_bytes(d_get(ctx->token, CONFIG_KEY("sync_key"))); if (sync_key.len) { zkcrypto_pk_from_seed(sync_key, conf->sync_key); zkcrypto_pk_to_pubkey(conf->sync_key, conf->pub_key); zkcrypto_pubkey_hash(bytes(conf->pub_key, 32), conf->pub_key_hash_pk); } - bytes_t* main_contract = d_get_bytes(ctx->token, key("main_contract")); + bytes_t* main_contract = d_get_bytes(ctx->token, CONFIG_KEY("main_contract")); if (main_contract && main_contract->len == 20) memcpy(conf->main_contract = _malloc(20), main_contract->data, 20); - d_token_t* st = d_get(ctx->token, key("signer_type")); + d_token_t* st = d_get(ctx->token, CONFIG_KEY("signer_type")); if (st) conf->sign_type = get_sign_type(st); else if (conf->sign_type == 0) conf->sign_type = ZK_SIGN_PK; - conf->version = (uint32_t) d_intd(d_get(ctx->token, key("version")), conf->version); - d_token_t* musig = d_get(ctx->token, key("musig_pub_keys")); + conf->version = (uint32_t) d_intd(d_get(ctx->token, CONFIG_KEY("version")), conf->version); + d_token_t* musig = d_get(ctx->token, CONFIG_KEY("musig_pub_keys")); if (musig && d_type(musig) == T_BYTES && d_len(musig) % 32 == 0) { if (conf->musig_pub_keys.data) _free(conf->musig_pub_keys.data); conf->musig_pub_keys = bytes(_malloc(d_len(musig)), musig->len); memcpy(conf->musig_pub_keys.data, musig->data, musig->len); } - d_token_t* urls = d_get(ctx->token, key("musig_urls")); + d_token_t* urls = d_get(ctx->token, CONFIG_KEY("musig_urls")); if (urls) { if (conf->musig_urls) { for (unsigned int i = 0; i < conf->musig_pub_keys.len / 32; i++) { @@ -294,23 +294,23 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { if (s) conf->musig_urls[i] = _strdupn(s, -1); } } - d_token_t* create2 = d_get(ctx->token, key("create2")); + d_token_t* create2 = d_get(ctx->token, CONFIG_KEY("create2")); if (create2) { conf->sign_type = ZK_SIGN_CREATE2; if (!conf->create2) conf->create2 = _calloc(1, sizeof(zk_create2_t)); - bytes_t* t = d_get_bytes(create2, key("creator")); + bytes_t* t = d_get_bytes(create2, CONFIG_KEY("creator")); if (t && t->len == 20) memcpy(conf->create2->creator, t->data, 20); - t = d_get_bytes(create2, key("saltarg")); + t = d_get_bytes(create2, CONFIG_KEY("saltarg")); if (t && t->len == 32) memcpy(conf->create2->salt_arg, t->data, 32); - t = d_get_bytes(create2, key("codehash")); + t = d_get_bytes(create2, CONFIG_KEY("codehash")); if (t && t->len == 32) memcpy(conf->create2->codehash, t->data, 32); } - d_token_t* incentive = d_get(ctx->token, key("incentive")); + d_token_t* incentive = d_get(ctx->token, CONFIG_KEY("incentive")); if (incentive) { if (!conf->incentive) conf->incentive = _calloc(1, sizeof(pay_criteria_t)); for (d_iterator_t iter = d_iter(incentive); iter.left; d_iter_next(&iter)) { - if (iter.token->key == key("nodes")) { + if (iter.token->key == CONFIG_KEY("nodes")) { conf->incentive->payed_nodes = d_int(iter.token); in3_req_t c = {0}; c.client = ctx->client; @@ -320,9 +320,9 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { return ret; } } - else if (iter.token->key == key("max_price")) + else if (iter.token->key == CONFIG_KEY("max_price")) conf->incentive->max_price_per_hundred_igas = d_long(iter.token); - else if (iter.token->key == key("token")) { + else if (iter.token->key == CONFIG_KEY("token")) { _free(conf->incentive->token); conf->incentive->token = _strdupn(d_string(iter.token), -1); } diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index dc77de8b9..cb49990da 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -168,7 +168,7 @@ static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { switch (action) { case PLGN_ACT_CONFIG_SET: { in3_configure_ctx_t* ctx = action_ctx; - if (ctx->token->key == key("key")) { + if (ctx->token->key == CONFIG_KEY("key")) { if (d_type(ctx->token) != T_BYTES || d_len(ctx->token) != 32) { ctx->error_msg = _strdupn("invalid key-length, must be 32", -1); return IN3_EINVAL; @@ -176,7 +176,7 @@ static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { eth_set_request_signer(ctx->client, ctx->token->data); return IN3_OK; } - if (ctx->token->key == key("pk")) { + if (ctx->token->key == CONFIG_KEY("pk")) { if (d_type(ctx->token) == T_BYTES) { if (d_len(ctx->token) != 32) { ctx->error_msg = _strdupn("invalid key-length, must be 32", -1); diff --git a/c/src/verifier/btc/btc.c b/c/src/verifier/btc/btc.c index 59020e5fb..c6fb1ab8d 100644 --- a/c/src/verifier/btc/btc.c +++ b/c/src/verifier/btc/btc.c @@ -501,9 +501,9 @@ static in3_ret_t handle_btc(void* pdata, in3_plugin_act_t action, void* pctx) { } case PLGN_ACT_CONFIG_SET: { in3_configure_ctx_t* cctx = pctx; - if (cctx->token->key == key("maxDAP")) + if (cctx->token->key == CONFIG_KEY("maxDAP")) conf->max_daps = d_int(cctx->token); - else if (cctx->token->key == key("maxDiff")) + else if (cctx->token->key == CONFIG_KEY("maxDiff")) conf->max_diff = d_int(cctx->token); else return IN3_EIGNORE; diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 95c87adc4..32076778a 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -19,9 +19,19 @@ const getRPCVerifiers = () => grep('VERIFY_RPC', '../c/src').reduce((p, line) => } return p }, []) +const getConfigs = () => grep('CONFIG_KEY', '../c/src').reduce((p, line) => { + let r = (/(.*?\.c).*?CONFIG_KEY\(\"([^\"]+)(.*)/gm).exec(line) + const file = r[1] + if (!exists(p, r[2])) p.push({ file, name: r[2], type: 'config' }) + while (r = (/(.*?CONFIG_KEY)\(\"([^\"]+)(.*)/gm).exec(r[3])) { + if (!exists(p, r[2])) p.push({ file, name: r[2], type: 'config' }) + } + return p +}, []) +const lastToken = l => l.substring(l.lastIndexOf(' ') + 1); const label = (n, l) => l ? ('\033[' + l + 'm' + n.replace('*', '') + '\033[0m') : n const is_allowed = ['btc_proofTarget'] -const check = (list, name, c) => list.indexOf(name) != -1 ? ((++res[c]) && ' \u2705 ') : (is_allowed.indexOf(name) == -1 ? ' \u274c ' : ((++res[c]) && ' \u274e ')) +const check = (list, name, c) => list.indexOf(name) != -1 ? ((++res[c]) && ' \u2705 ') : ((list.length && is_allowed.indexOf(name) == -1) ? ' \u274c ' : ((++res[c]) && ' \u274e ')) const bindings = { doc: grep('\"^### \"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('# ') + 2).trim()), java: strings('../java/src', '"'), @@ -34,6 +44,7 @@ const bindings = { } const res = Object.keys(bindings).reduce((p, c) => ({ ...p, [c]: 0 }), {}) const all_rpc_names = [...getRPCHandlers(), ...getRPCVerifiers()].map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i) +const configs = getConfigs().map(_ => _.name).filter((v, i, a) => a.indexOf(v) === i).sort() bindings.doc.filter(_ => all_rpc_names.indexOf(_) == -1).forEach(_ => all_rpc_names.push(_ + '*')) all_rpc_names.sort() console.log('RPC-Method'.padEnd(40) + ' ' + Object.keys(bindings).map(_ => _.padEnd(7)).join('')) @@ -50,6 +61,27 @@ all_rpc_names.forEach(rpc => { console.log(label(l.padEnd(40), rpc.endsWith('*') ? '31' : (Object.keys(bindings).length == c ? '32' : '33')) + ' : ' + s) }) +console.log('\nConfig'.padEnd(40) + ' ' + Object.keys(bindings).map(_ => _.padEnd(7)).join('')) +console.log('-'.padEnd(45 + 7 * Object.keys(bindings).length, '-')) +bindings.doc = grep('\"\\*\\*[a-zA-Z0-9_]+\\*\\*\"', '../../../doc/docs/rpc.md').map(_ => _.substring(_.indexOf('**') + 2, _.lastIndexOf('**')).trim()) +bindings.wasm = grep('\"^[ ]*[a-zA-Z0-9_]+[\\?]*:.*\"', '../wasm/src').map(_ => lastToken(_.substring(0, _.lastIndexOf(':')).replace('?', '').trim())) +bindings.autocmpl = [] +bindings.c_api = [] +bindings.python = grep("\"self\\.[a-zA-Z0-9_]+\"", '../python/in3/model.py').map(_ => ((/self.([a-zA-Z0-9_]+)/gm).exec(_) || ["", ""])[1]) + + +for (const conf of configs) { + let s = '', c = 0 + Object.keys(bindings).forEach(k => { + c -= res[k] + s += check(bindings[k], conf, k) + c += res[k] + }) + console.log(label(conf.padEnd(40), (Object.keys(bindings).length == c ? '32' : '33')) + ' : ' + s) +} + + + console.log("\nSummary:") -Object.keys(res).forEach(k => console.log(k.padEnd(8) + ': ' + (res[k] * 100 / all_rpc_names.length).toFixed(0) + ' % ')) +Object.keys(res).forEach(k => console.log(k.padEnd(8) + ': ' + (res[k] * 100 / (all_rpc_names.length + configs.length)).toFixed(0) + ' % ')) From f6c56907462a8924cb7743043c646a867e2b1d73 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 29 Mar 2021 18:19:47 +0200 Subject: [PATCH 039/221] add config from yml --- c/src/cmd/in3/args.h | 70 +++++++++++ c/src/cmd/in3/config.c | 12 ++ c/src/cmd/in3/main.c | 55 ++++++--- c/src/core/client/rpc.yml | 36 ++++-- c/src/nodeselect/full/nodeselect_def.c | 7 +- c/src/nodeselect/full/rpc.yml | 15 ++- c/src/pay/zksync/rpc.yml | 31 +++++ c/src/signer/pk-signer/rpc.yml | 2 + c/src/verifier/btc/rpc.yml | 4 + scripts/_in3.sh | 86 ++++++++++--- scripts/_in3.template | 28 ++--- scripts/build_rpc_docu.js | 162 +++++++++++++++++-------- 12 files changed, 384 insertions(+), 124 deletions(-) create mode 100644 c/src/cmd/in3/args.h create mode 100644 c/src/cmd/in3/config.c diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h new file mode 100644 index 000000000..6bd8e6513 --- /dev/null +++ b/c/src/cmd/in3/args.h @@ -0,0 +1,70 @@ +const char* help_args = "\ +--chainId -c the chainId or the name of a known chain\n\ +--finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ +--includeCode if true, the request should include the codes of all accounts\n\ +--maxAttempts -a max number of attempts in case a response is rejected\n\ +--keepIn3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ +--useBinary if true the client will use binary format\n\ +--experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ +--timeout specifies the number of milliseconds before the request times out\n\ +--proof -p if true the nodes should send a proof of the response\n\ +--replaceLatestBlock -l if specified, the blocknumber *latest* will be replaced by blockNumber- specified value\n\ +--autoUpdateList if true the nodelist will be automaticly updated if the lastBlock is newer\n\ +--signatureCount -s number of signatures requested in order to verify the blockhash\n\ +--bootWeights if true, the first request (updating the nodelist) will also fetch the current health status and use...\n\ +--useHttp if true the client will try to use http instead of https\n\ +--minDeposit min stake of the server\n\ +--nodeProps used to identify the capabilities of the node\n\ +--requestCount -rc the number of request send in parallel when getting an answer\n\ +--rpc url of one or more direct rpc-endpoints to use\n\ +--nodes defining the nodelist\n\ +--nodes.contract address of the registry contract\n\ +--nodes.whiteListContract address of the whiteList contract\n\ +--nodes.whiteList manual whitelist\n\ +--nodes.registryId identifier of the registry\n\ +--nodes.needsUpdate if set, the nodeList will be updated before next request\n\ +--nodes.avgBlockTime average block time (seconds) for this chain\n\ +--nodes.verifiedHashes if the client sends an array of blockhashes the server will not deliver any signatures or blockheade...\n\ +--nodes.verifiedHashes.block block number\n\ +--nodes.verifiedHashes.hash verified hash corresponding to block number\n\ +--nodes.nodeList manual nodeList\n\ +--nodes.nodeList.url URL of the node\n\ +--nodes.nodeList.address address of the node\n\ +--nodes.nodeList.props used to identify the capabilities of the node (defaults to 0xFFFF)\n\ +--zksync configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per defaul...\n\ +--zksync.provider_url -zks url of the zksync-server (if not defined it will be choosen depending on the chain)\n\ +--zksync.account -zka the account to be used\n\ +--zksync.sync_key -zsk the seed used to generate the sync_key\n\ +--zksync.main_contract address of the main contract- If not specified it will be taken from the server\n\ +--zksync.signer_type -zkat type of the account\n\ +--zksync.musig_pub_keys -zms concatenated packed public keys (32byte) of the musig signers\n\ +--zksync.musig_urls -zmu a array of strings with urls based on the `musig_pub_keys`\n\ +--zksync.create2 -zc2 create2-arguments for sign_type `create2`\n\ +--zksync.create2.creator The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )\n\ +--zksync.create2.saltarg a salt-argument, which will be added to the pubkeyhash and create the create2-salt\n\ +--zksync.create2.codehash the hash of the actual deploy-tx including the constructor-arguments\n\ +--key -k the client key to sign requests\n\ +--pk -pk registers raw private keys as signers for transactions\n\ +--btc configure the Bitcoin verification\n\ +--btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ +--btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n"; + + const char* aliases[] = { + "c","chainId", + "f","finality", + "a","maxAttempts", + "x","experimental=true", + "p","proof", + "l","replaceLatestBlock", + "s","signatureCount", + "rc","requestCount", + "zks","zksync.provider_url", + "zka","zksync.account", + "zsk","zksync.sync_key", + "zkat","zksync.signer_type", + "zms","zksync.musig_pub_keys", + "zmu","zksync.musig_urls", + "zc2","zksync.create2", + "k","key", + "pk","pk", + NULL}; diff --git a/c/src/cmd/in3/config.c b/c/src/cmd/in3/config.c new file mode 100644 index 000000000..5cded2511 --- /dev/null +++ b/c/src/cmd/in3/config.c @@ -0,0 +1,12 @@ + + +const char* help = "options"; +const char** aliases = { + "p", "proof", + "l", "latest", + "zks", "zksync.provider_url", + --key - k + NULL}; + +bool configure() { +} diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index b8f4d3b3e..dd65a3c65 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -75,6 +75,7 @@ #include "../../signer/pk-signer/signer.h" #include "../../tools/recorder/recorder.h" #include "../../verifier/eth1/nano/chainspec.h" +#include "args.h" #include "in3_storage.h" #include #include @@ -91,12 +92,8 @@ void show_help(char* name) { recorder_print(0, "Usage: %s method ... \n\ \n\ --c, -chain the chain to use. (mainnet, goerli, ewc, btc, ipfs, local or any RPCURL)\n\ --a max number of attempts before giving up (default 5)\n\ --rc number of request per try (default 1)\n\ +%s\n\ -ns no stats if set requests will not be part of the official metrics and considered a service request\n\ --p, -proof specifies the Verification level: (none, standard(default), full)\n\ --md specifies the minimum Deposit of a node in order to be selected as a signer\n\ -np short for -p none\n\ -eth converts the result (as wei) to ether.\n\ -l, -latest replaces \"latest\" with latest BlockNumber - the number of blocks given.\n\ @@ -200,7 +197,7 @@ in3_weights\n\ in3_ens \n\ resolves a ens-domain. field can be addr(deault), owner, resolver or hash\n\ \n", - name); + name, help_args); } _Noreturn static void die(char* msg) { recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); @@ -252,11 +249,33 @@ void read_pass(char* pw, int pwsize) { recorder_print(1, COLORT_RESETHIDDEN); //reveal typing } -static bool configure_arg(in3_t* c, char* arg, int* i, int argc) { - UNUSED_VAR(i); +static bool configure_arg(in3_t* c, char** args, int* index, int argc) { + UNUSED_VAR(index); UNUSED_VAR(argc); - char* value = strchr(arg, '='); - char* name = NULL; + const char* arg = args[*index]; + char* value = strchr(arg, '='); + char* name = NULL; + if (arg[0] != '-') return false; + if (arg[1] && arg[1] != '-') { + for (int i = 0; aliases[i]; i += 2) { + if (strcmp(aliases[i], arg + 1) == 0) { + name = alloca(strlen(aliases[i + 1] + 3)); + name[0] = (name[1] = '-'); + strcpy(name + 2, aliases[i + 1]); + value = strchr(name, '='); + if (!value) { + if (argc - 1 <= *index) die("missing value for option"); + *index += 1; + value = args[*index]; + } + else + *value = 0; + break; + } + } + if (!name) die("unknown option!"); + } + if (!value) { // die("invalid syntax for --key=value"); value = "true"; @@ -265,10 +284,13 @@ static bool configure_arg(in3_t* c, char* arg, int* i, int argc) { } else { value++; - name = alloca(value - arg); - strncpy(name, arg, value - arg - 1); - name[value - arg - 1] = 0; + if (!name) { + name = alloca(value - arg); + strncpy(name, arg, value - arg - 1); + name[value - arg - 1] = 0; + } } + if (name[0] == '-' && name[1] == '-') { name += 2; char* p = strtok(name, "."); @@ -279,7 +301,7 @@ static bool configure_arg(in3_t* c, char* arg, int* i, int argc) { char* next = strtok(NULL, "."); if (!next) { if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) - sb_print(&sb, "\"%s\":", p, value); + sb_print(&sb, "\"%s\":%s", p, value); else sb_print(&sb, "\"%s\":\"%s\"", p, value); break; @@ -290,7 +312,6 @@ static bool configure_arg(in3_t* c, char* arg, int* i, int argc) { continue; } for (; b; b--) sb_add_char(&sb, '}'); - in3_log_info("configure %s \n", sb.data); char* error = in3_configure(c, sb.data); if (error) die(error); @@ -920,8 +941,6 @@ int main(int argc, char* argv[]) { run_test_request = 1; else if (strcmp(argv[i], "-thr") == 0) run_test_request = 2; - else if (strcmp(argv[i], "-x") == 0) - c->flags |= FLAGS_ALLOW_EXPERIMENTAL; else if (strcmp(argv[i], "-fo") == 0) recorder_write_start(c, argv[++i], argc, argv); else if (strcmp(argv[i], "-fi") == 0) @@ -1028,7 +1047,7 @@ int main(int argc, char* argv[]) { i++; } // now handle arguments for special methods - else if (configure_arg(c, argv[i], &i, argc)) + else if (configure_arg(c, argv, &i, argc)) continue; else { if (method == NULL) diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index cc5d39790..acc82272c 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -10,10 +10,18 @@ in3: chainId: type: uint | string - descr: the chainId or the name of a known chain (`mainnet`,`goerli`,`ewc`,`btc` or `ipfs`). It defines the nodelist to connect to. + descr: the chainId or the name of a known chain. It defines the nodelist to connect to. example: goerli optional: true default: mainnet + enum: + mainnet: Mainnet Chain + goerli: Goerli Testnet + ewc: Energy WebFoundation + btc: Bitcoin + ipfs: ipfs + local: local-chain + cmd: c finality: type: uint | string @@ -21,6 +29,7 @@ in3: example: 50 optional: true default: 0 + cmd: f includeCode: type: bool @@ -35,6 +44,7 @@ in3: example: 1 optional: true default: 7 + cmd: a keepIn3: type: bool @@ -56,6 +66,7 @@ in3: example: true optional: true default: false + cmd: x timeout: descr: specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. @@ -66,16 +77,22 @@ in3: proof: descr: if true the nodes should send a proof of the response. If set to none, verification is turned off completly. - type: string (none,standard,full) + type: string optional: true + enum: + - none + - standard + - full example: none default: standard + cmd: p replaceLatestBlock: descr: if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. type: uint optional: true example: 6 + cmd: l # rpc-commands @@ -94,13 +111,12 @@ in3: maxAttempts: 4 nodeLimit: 10 nodes: - "0x1": - nodeList: - - address: "0x1234567890123456789012345678901234567890" - url: "https://mybootnode-A.com" - props: "0xFFFF" - - address: "0x1234567890123456789012345678901234567890" - url: "https://mybootnode-B.com" - props: "0xFFFF" + nodeList: + - address: "0x1234567890123456789012345678901234567890" + url: "https://mybootnode-A.com" + props: "0xFFFF" + - address: "0x1234567890123456789012345678901234567890" + url: "https://mybootnode-B.com" + props: "0xFFFF" response: true diff --git a/c/src/nodeselect/full/nodeselect_def.c b/c/src/nodeselect/full/nodeselect_def.c index d0923fa6a..31e3c4a46 100644 --- a/c/src/nodeselect/full/nodeselect_def.c +++ b/c/src/nodeselect/full/nodeselect_def.c @@ -199,9 +199,14 @@ static in3_ret_t config_set(in3_nodeselect_def_t* data, in3_configure_ctx_t* ctx EXPECT_TOK_U16(token); w->node_limit = (uint16_t) d_int(token); } - else if (token->key == CONFIG_KEY("nodeRegistry")) { + else if (token->key == CONFIG_KEY("nodeRegistry") || token->key == CONFIG_KEY("servers") || token->key == CONFIG_KEY("nodes")) { EXPECT_TOK_OBJ(token); + // this is legacy-support, if the object has a key with the chain_id, we simply use the value. + char node_id[10]; + sprintf(node_id, "0x%x", ctx->client->chain.chain_id); + if (d_get(token, key(node_id))) token = d_get(token, key(node_id)); + // this is changing the nodelist config, so we need to make sure we have our own nodelist TRY(nodelist_seperate_from_registry(&data, w)) diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index b63e48124..2b5384dcf 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -6,7 +6,7 @@ in3: type: bool optional: true descr: if true the nodelist will be automaticly updated if the lastBlock is newer. - example: true + example: false default: true signatureCount: @@ -15,6 +15,7 @@ in3: optional: true example: 2 default: 1 + cmd: s bootWeights: descr: if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. @@ -34,6 +35,7 @@ in3: descr: min stake of the server. Only nodes owning at least this amount will be chosen. type: uint optional: true + example: 10000000 nodeProps: descr: used to identify the capabilities of the node. @@ -47,18 +49,24 @@ in3: optional: true example: 3 default: 2 + cmd: + - rc rpc: descr: url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. type: string optional: true + example: http://loalhost:8545 nodes: descr: defining the nodelist. collection of JSON objects with chain Id (hex string) as key. optional: true example: - "0x1": - nodeList: [] + contract: '0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f' + nodeList: + - address: "0x45d45e6ff99e6c34a235d263965910298985fcfe" + url: "https://in3-v2.slock.it/mainnet/nd-1" + props: "0xFFFF" type: contract: descr: address of the registry contract. (This is the data-contract!) @@ -102,6 +110,7 @@ in3: nodeList: descr: manual nodeList. As Value a array of Node-Definitions is expected. optional: true + array: true type: url: descr: URL of the node. diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index c5276f049..6f0b5b108 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -13,22 +13,44 @@ zksync: zksync: descr: configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + example: + - account: '0x995628aa92d6a016da55e7de8b1727e1eb97d337' + sync_key: '0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816' + signer_type: contract + - account: '0x995628aa92d6a016da55e7de8b1727e1eb97d337' + sync_key: '0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816' + signer_type: create2 + create2: + creator: '0x6487c3ae644703c1f07527c18fe5569592654bcb' + saltarg: '0xb90306e2391fefe48aa89a8e91acbca502a94b2d734acc3335bb2ff5c266eb12' + codehash: '0xd6af3ee91c96e29ddab0d4cb9b5dd3025caf84baad13bef7f2b87038d38251e5' + - account: '0x995628aa92d6a016da55e7de8b1727e1eb97d337' + signer_type: pk + musig_pub_keys: '0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d8160x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816' + sync_key: '0xe8f2ee64be83c0ab9466b0490e4888dbf5a070fd1d82b567e33ebc90457a5734' + musig_urls: + - null + - 'https://approver.service.com' + type: provider_url: descr: url of the zksync-server (if not defined it will be choosen depending on the chain) type: string optional: true default: https://api.zksync.io/jsrpc + cmd: zks account: descr: the account to be used. if not specified, the first signer will be used. type: address optional: true + cmd: zka sync_key: descr: the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. type: bytes32 optional: true + cmd: zsk main_contract: descr: address of the main contract- If not specified it will be taken from the server. @@ -38,21 +60,30 @@ zksync: signer_type: descr: type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. type: string + enum: + pk: Private matching the account is used ( for EOA) + contract: Contract Signature based EIP 1271 + create2: create2 optionas are used + optional: true default: pk + cmd: zkat musig_pub_keys: descr: concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. type: bytes optional: true + cmd: zms musig_urls: descr: a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. type: string[] optional: true + cmd: zmu create2: descr: create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + cmd: zc2 optional: true type: creator: diff --git a/c/src/signer/pk-signer/rpc.yml b/c/src/signer/pk-signer/rpc.yml index 764eae59c..3e1cc28df 100644 --- a/c/src/signer/pk-signer/rpc.yml +++ b/c/src/signer/pk-signer/rpc.yml @@ -8,12 +8,14 @@ in3: descr: the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) example: "0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" optional: true + cmd: k pk: type: bytes32|bytes32[] descr: registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) example: ["0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe"] optional: true + cmd: pk # RPC in3_addRawKey: diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 894ca4175..d65c3ddaf 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -112,6 +112,10 @@ btc: btc: descr: configure the Bitcoin verification + example: + maxDAP: 30 + maxDiff: 5 + type: maxDAP: descr: max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 25be8ff50..487315971 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -6,6 +6,13 @@ subcmds=( 'call: calls a contract ...args' 'abi_encode: encodes the arguments as described in the method signature using ABI-Encoding. ...args' 'abi_decode: decodes the data based on the signature.. ' + 'pk2address: extracts the public address from a private key ' + 'pk2public: extracts the public key from a private key ' + 'ecrecover: extracts the address and public key from a signature ' + 'key: reads the private key from JSON-Keystore file and returns the private key. ' + 'createkey: generates a random key' + 'in3_checksumAddress: display the address as checksumAddress' + 'keccak: calculate the keccak hash of the ' 'btc_proofTarget: Whenever the client is not able to trust the changes of the target (which is the case if a block can... ' 'getbestblockhash: Returns the hash of the best (tip) block in the longest blockchain' 'getblock: Returns data of block for given block hash ' @@ -85,15 +92,70 @@ subcmds=( ) args=( - '-c[chain]:chain id:(mainnet goerli ewc ipfs btc local)' +'--chainId=[the chainId or the name of a known chain]:chainId:(mainnet goerli ewc btc ipfs local)' +'-c[the chainId or the name of a known chain]:chainId:(mainnet goerli ewc btc ipfs local)' +'--finality=[the number in percent needed in order reach finality (% of signature of the validators)]:finality:()' +'-f[the number in percent needed in order reach finality (% of signature of the validators)]:finality:()' +'--includeCode[if true, the request should include the codes of all accounts]' +'--maxAttempts=[max number of attempts in case a response is rejected]:maxAttempts:()' +'-a[max number of attempts in case a response is rejected]:maxAttempts:()' +'--keepIn3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' +'--useBinary[if true the client will use binary format]' +'--experimental[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' +'-x[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' +'--timeout=[specifies the number of milliseconds before the request times out]:timeout:()' +'--proof=[if true the nodes should send a proof of the response]:proof:(0 1 2)' +'-p[if true the nodes should send a proof of the response]:proof:(0 1 2)' +'--replaceLatestBlock=[if specified, the blocknumber *latest* will be replaced by blockNumber- specified value]:replaceLatestBlock:()' +'-l[if specified, the blocknumber *latest* will be replaced by blockNumber- specified value]:replaceLatestBlock:()' +'--autoUpdateList[if true the nodelist will be automaticly updated if the lastBlock is newer]' +'--signatureCount=[number of signatures requested in order to verify the blockhash]:signatureCount:()' +'-s[number of signatures requested in order to verify the blockhash]:signatureCount:()' +'--bootWeights[if true, the first request (updating the nodelist) will also fetch the current health status and use...]' +'--useHttp[if true the client will try to use http instead of https]' +'--minDeposit=[min stake of the server]:minDeposit:()' +'--nodeProps=[used to identify the capabilities of the node]:nodeProps:()' +'--requestCount=[the number of request send in parallel when getting an answer]:requestCount:()' +'-rc[the number of request send in parallel when getting an answer]:requestCount:()' +'--rpc=[url of one or more direct rpc-endpoints to use]:rpc:()' +'--nodes.contract=[address of the registry contract]:contract:()' +'--nodes.whiteListContract=[address of the whiteList contract]:whiteListContract:()' +'--nodes.whiteList=[manual whitelist]:whiteList:()' +'--nodes.registryId=[identifier of the registry]:registryId:()' +'--nodes.needsUpdate[if set, the nodeList will be updated before next request]' +'--nodes.avgBlockTime=[average block time (seconds) for this chain]:avgBlockTime:()' +'--nodes.verifiedHashes.block=[block number]:block:()' +'--nodes.verifiedHashes.hash=[verified hash corresponding to block number]:hash:()' +'--nodes.nodeList.url=[URL of the node]:url:()' +'--nodes.nodeList.address=[address of the node]:address:()' +'--nodes.nodeList.props=[used to identify the capabilities of the node (defaults to 0xFFFF)]:props:()' +'--zksync.provider_url=[url of the zksync-server (if not defined it will be choosen depending on the chain)]:provider_url:()' +'-zks[url of the zksync-server (if not defined it will be choosen depending on the chain)]:provider_url:()' +'--zksync.account=[the account to be used]:account:()' +'-zka[the account to be used]:account:()' +'--zksync.sync_key=[the seed used to generate the sync_key]:sync_key:()' +'-zsk[the seed used to generate the sync_key]:sync_key:()' +'--zksync.main_contract=[address of the main contract- If not specified it will be taken from the server]:main_contract:()' +'--zksync.signer_type=[type of the account]:signer_type:(pk contract create2)' +'-zkat[type of the account]:signer_type:(pk contract create2)' +'--zksync.musig_pub_keys=[concatenated packed public keys (32byte) of the musig signers]:musig_pub_keys:()' +'-zms[concatenated packed public keys (32byte) of the musig signers]:musig_pub_keys:()' +'--zksync.musig_urls=[a array of strings with urls based on the `musig_pub_keys`]:musig_urls:()' +'-zmu[a array of strings with urls based on the `musig_pub_keys`]:musig_urls:()' +'--zksync.create2.creator=[The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )]:creator:()' +'--zksync.create2.saltarg=[a salt-argument, which will be added to the pubkeyhash and create the create2-salt]:saltarg:()' +'--zksync.create2.codehash=[the hash of the actual deploy-tx including the constructor-arguments]:codehash:()' +'--key=[the client key to sign requests]:key:()' +'-k[the client key to sign requests]:key:()' +'--pk=[registers raw private keys as signers for transactions]:pk:()' +'-pk[registers raw private keys as signers for transactions]:pk:()' +'--btc.maxDAP=[max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets]:maxDAP:()' +'--btc.maxDiff=[max increase (in percent) of the difference between targets when accepting new targets]:maxDiff:()' '-st[the type of the signature data]:st:(eth_sign raw hash)' - '-p[the Verification level]:p:(none standard full)' '-pwd[password to unlock the key]:pwd:()' '-np[short for -p none]' '-ns[short for no stats, which does count this request in the public stats]' '-eth[onverts the result (as wei) to ether]' - '-l[replaces "latest" with latest BlockNumber - the number of blocks given]:latest:(1 2 3 4 5 6 7 8 9 10)' - '-s[number of signatures to use when verifying]:sigs:(1 2 3 4 5 6 7 8 9 10)' '-port[if specified it will run as http-server listening to the given port]:port:(8545)' '-am[Allowed Methods when used with -port as comma seperated list of methods]:allowed_methods:()' '-b[the blocknumber to use when making calls]:b:(latest earliest 0x)' @@ -102,7 +164,6 @@ args=( '-gas[the gas limit to use when sending transactions]:gas:(21000 100000 250000 500000 1000000 2000000)' '-gas_price[the gas price to use within a tx]:gas_price:()' '-pk[the private key as raw or path to the keystorefile]:pk:()' - '-k[the private key to sign request for incetives payments]:k:()' '-help[displays this help message]' '-tr[runs test request when showing in3_weights]' '-thr[runs test request including health-check when showing in3_weights]' @@ -119,25 +180,10 @@ args=( '-os[only sign, do not send the raw Transaction]' '-ri[read response from stdin]' '-ro[write raw response to stdout]' - '-a[max number of attempts before giving up (default 5)]:attempts:(1 2 3 4 5 6 7 8 9)' - '-rc[number of request per try (default 1)]:requestCount:(1 2 3 4 5 6 7 8 9)' '-fi[read recorded request from file]:fi:()' '-fo[recorded request and write to file]:fo:()' '-nl[a comma seperated list of urls as address:url to be used as fixed nodelist]:nl:()' '-bn[a comma seperated list of urls as address:url to be used as boot nodes]:bn:()' - '-zks[URL of the zksync-server]:zks:(https\://api.zksync.io/jsrpc http\://localhost\:3030)' - '-zkss[zksync signatures to pass along when signing]:zkss:()' - '-zka[zksync account to use]:zka:()' - '-zkat[zksync account type]:zkat:(pk contract create2)' - '-zsk[zksync signer seed - if not set this key will be derrived from account unless create2]:zsk:()' - '-zc2[zksync create2 arguments in the form ::. if set the account type is also changed to create2]:zc2:()' - '-zms[public keys of a musig schnorr signatures to sign with]:zms:()' - '-zmu[url for signing service matching the first remote public key]:zmu:(http\://localhost\:8080)' - '-zvpm[method for calling to verify the proof in server mode]:zvpm:(iamo_zksync_verify_signatures)' - '-zcpm[method for calling to create the proof]:zcpm:(iamo_zksync_create_signatures)' - '-idk[iamo device key]:idk:()' - '-imc[the master copy address to be used]:imc:()' - '-if[iamo factory address]:if:()' ':method:{_describe command subcmds}' ':arg1:{_describe command sig_in3 -- sig_erc20 -- sig_ms}' diff --git a/scripts/_in3.template b/scripts/_in3.template index 6a68a366c..efdb7d9ba 100755 --- a/scripts/_in3.template +++ b/scripts/_in3.template @@ -6,19 +6,23 @@ subcmds=( 'call: calls a contract ...args' 'abi_encode: encodes the arguments as described in the method signature using ABI-Encoding. ...args' 'abi_decode: decodes the data based on the signature.. ' + 'pk2address: extracts the public address from a private key ' + 'pk2public: extracts the public key from a private key ' + 'ecrecover: extracts the address and public key from a signature ' + 'key: reads the private key from JSON-Keystore file and returns the private key. ' + 'createkey: generates a random key' + 'in3_checksumAddress: display the address as checksumAddress' + 'keccak: calculate the keccak hash of the ' $CMDS ) args=( - '-c[chain]:chain id:(mainnet goerli ewc ipfs btc local)' +$CONFS '-st[the type of the signature data]:st:(eth_sign raw hash)' - '-p[the Verification level]:p:(none standard full)' '-pwd[password to unlock the key]:pwd:()' '-np[short for -p none]' '-ns[short for no stats, which does count this request in the public stats]' '-eth[onverts the result (as wei) to ether]' - '-l[replaces "latest" with latest BlockNumber - the number of blocks given]:latest:(1 2 3 4 5 6 7 8 9 10)' - '-s[number of signatures to use when verifying]:sigs:(1 2 3 4 5 6 7 8 9 10)' '-port[if specified it will run as http-server listening to the given port]:port:(8545)' '-am[Allowed Methods when used with -port as comma seperated list of methods]:allowed_methods:()' '-b[the blocknumber to use when making calls]:b:(latest earliest 0x)' @@ -27,7 +31,6 @@ args=( '-gas[the gas limit to use when sending transactions]:gas:(21000 100000 250000 500000 1000000 2000000)' '-gas_price[the gas price to use within a tx]:gas_price:()' '-pk[the private key as raw or path to the keystorefile]:pk:()' - '-k[the private key to sign request for incetives payments]:k:()' '-help[displays this help message]' '-tr[runs test request when showing in3_weights]' '-thr[runs test request including health-check when showing in3_weights]' @@ -44,25 +47,10 @@ args=( '-os[only sign, do not send the raw Transaction]' '-ri[read response from stdin]' '-ro[write raw response to stdout]' - '-a[max number of attempts before giving up (default 5)]:attempts:(1 2 3 4 5 6 7 8 9)' - '-rc[number of request per try (default 1)]:requestCount:(1 2 3 4 5 6 7 8 9)' '-fi[read recorded request from file]:fi:()' '-fo[recorded request and write to file]:fo:()' '-nl[a comma seperated list of urls as address:url to be used as fixed nodelist]:nl:()' '-bn[a comma seperated list of urls as address:url to be used as boot nodes]:bn:()' - '-zks[URL of the zksync-server]:zks:(https\://api.zksync.io/jsrpc http\://localhost\:3030)' - '-zkss[zksync signatures to pass along when signing]:zkss:()' - '-zka[zksync account to use]:zka:()' - '-zkat[zksync account type]:zkat:(pk contract create2)' - '-zsk[zksync signer seed - if not set this key will be derrived from account unless create2]:zsk:()' - '-zc2[zksync create2 arguments in the form ::. if set the account type is also changed to create2]:zc2:()' - '-zms[public keys of a musig schnorr signatures to sign with]:zms:()' - '-zmu[url for signing service matching the first remote public key]:zmu:(http\://localhost\:8080)' - '-zvpm[method for calling to verify the proof in server mode]:zvpm:(iamo_zksync_verify_signatures)' - '-zcpm[method for calling to create the proof]:zcpm:(iamo_zksync_create_signatures)' - '-idk[iamo device key]:idk:()' - '-imc[the master copy address to be used]:imc:()' - '-if[iamo factory address]:if:()' ':method:{_describe command subcmds}' ':arg1:{_describe command sig_in3 -- sig_erc20 -- sig_ms}' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index af74eca0c..49ae2f9b3 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -1,5 +1,11 @@ const yaml = require('../wasm/test/node_modules/yaml') const fs = require('fs') +const doc_dir = process.argv[process.argv.length - 1] + +const rpc_doc = [] +const config_doc = [] +const main_help = [] +const main_aliases = [] let docs = {}, config = {}, types = {} const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) @@ -23,7 +29,7 @@ function scan(dir) { else if (f.isDirectory()) scan(dir + '/' + f.name) } } -function print_object(def, pad, useNum) { +function print_object(def, pad, useNum, doc) { let i = 1 for (const prop of Object.keys(def)) { let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' @@ -33,82 +39,129 @@ function print_object(def, pad, useNum) { if (p.optional) s += ' *(optional)*' if (p.descr) s += ' - ' + p.descr if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' + if (p.enum) s += '\n' + pad + 'Possible Values are:\n\n' + Object.keys(p.enum).map(v => pad + ' - `' + v + '` : ' + p.enum[v]).join('\n') + '\n' if (p.alias) s += '\n' + pad + 'The data structure of ' + prop + ' is the same as ' + link(p.alias) + '. See Details there.' - console.log(s) + doc.push(s) if (typeof pt === 'object') { - console.log('The ' + prop + ' object supports the following properties :\n' + pad) - print_object(pt, pad + ' ') + rpc_doc.push('The ' + prop + ' object supports the following properties :\n' + pad) + print_object(pt, pad + ' ', false, doc) } - if (p.example) console.log('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) - console.log(pad + '\n') + if (p.example) rpc_doc.push('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) + doc.push(pad + '\n') } } +function handle_config(conf, pre) { + for (const key of Object.keys(conf)) { + const c = conf[key] + if (!pre) { + let s = '\n## ' + key + '\n\n' + c.descr + if (c.optional) s += ' *This config is optional.*' + if (c.default) s += ' (default: `' + JSON.stringify(c.default) + '`)' + if (c.type) s += '\n\n Type: `' + (typeof c.type === 'string' ? c.type : 'object') + '`' + if (c.enum) s += '\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n' + config_doc.push(s) + if (typeof (c.type) === 'object') { + config_doc.push('The ' + key + ' object supports the following properties :\n') + print_object(c.type, '', false, config_doc) + } + if (c.example !== undefined) { + config_doc.push('\n*Example:*\n') + asArray(c.example).forEach(ex => { + config_doc.push('```sh') + if (typeof (ex) == 'object') + config_doc.push('> in3 ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') + else + config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') + config_doc.push('```\n') + config_doc.push('```js\nconst in3 = new IN3(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') + }) + + } + } + asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '","' + pre + key + (c.type == 'bool' ? '=true' : '') + '",')); + main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(6) + short_descr(c.descr)) + let s = '' + if (c.descr) s += '[' + short_descr(c.descr) + ']' + if (c.type != 'bool') + s += ':' + key + ':(' + (c.enum ? Object.keys(c.enum).join(' ') : '') + ')' + if (typeof (c.type) === 'object') + handle_config(c.type, pre + key + '.') + else { + zsh_conf.push("'--" + pre + key + (c.type != 'bool' ? '=' : '') + s + "'") + asArray(c.cmd).forEach(_ => zsh_conf.push("'-" + _ + s + "'")) + } + } +} +function short_descr(d) { + let zd = (d || '').trim() + if (zd.indexOf('.') >= 0) zd = zd.substr(0, zd.indexOf('.')) + if (zd.indexOf('\n') >= 0) zd = zd.substr(0, zd.indexOf('\n')) + if (zd.indexOf('[') >= 0) zd = zd.substr(0, zd.indexOf('[')) + if (zd.length > 100) zd = zd.substr(0, 100) + '...' + return zd +} scan('../c/src') docs.in3.in3_config.params.config.type = config -console.log('# API RPC\n\n') -console.log('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') +rpc_doc.push('# API RPC\n\n') +rpc_doc.push('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') +config_doc.push('# Configuration\n\n') +config_doc.push('When creating a new Incubed Instance you can configure it. The Configuration depends on the registered plugins. This page describes the available configuration parameters.\n\n') const zsh_complete = fs.readFileSync('_in3.template', 'utf8') -let zsh_cmds = [] +let zsh_cmds = [], zsh_conf = [] for (const s of Object.keys(docs).sort()) { const rpcs = docs[s] - console.log("## " + s + "\n\n") - if (rpcs.descr) console.log(rpcs.descr + '\n') + rpc_doc.push("## " + s + "\n\n") + if (rpcs.descr) rpc_doc.push(rpcs.descr + '\n') delete rpcs.descr for (const rpc of Object.keys(rpcs).sort()) { const def = rpcs[rpc] - let z = " '" + rpc + ': ' - let zd = (def.descr || (def.alias && rpcs[def.alias].descr) || '').trim() - if (zd.indexOf('.') >= 0) zd = zd.substr(0, zd.indexOf('.')) - if (zd.indexOf('\n') >= 0) zd = zd.substr(0, zd.indexOf('\n')) - if (zd.indexOf('[') >= 0) zd = zd.substr(0, zd.indexOf('[')) - if (zd.length > 100) zd = zd.substr(0, 100) + '...' - z += zd - - console.log('### ' + rpc + '\n\n') - asArray(def.alias).forEach(_ => console.log(rpc + ' is just an alias for ' + link(_) + '.See Details there.\n\n')) + let z = " '" + rpc + ': ' + short_descr((def.descr || (def.alias && rpcs[def.alias].descr) || '')) + + rpc_doc.push('### ' + rpc + '\n\n') + asArray(def.alias).forEach(_ => rpc_doc.push(rpc + ' is just an alias for ' + link(_) + '.See Details there.\n\n')) if (def.descr) - console.log(def.descr + '\n') + rpc_doc.push(def.descr + '\n') if (def.params) { - console.log("*Parameters:*\n") - print_object(def.params, '', true) - console.log() + rpc_doc.push("*Parameters:*\n") + print_object(def.params, '', true, rpc_doc) + rpc_doc.push() z += ' ' + Object.keys(def.params).map(_ => '<' + _ + '>').join(' ') } else if (!def.alias) - console.log("*Parameters:* - \n") + rpc_doc.push("*Parameters:* - \n") if (def.in3Params) { - console.log('The following in3-configuration will have an impact on the result:\n\n'); - print_object(getType(def.in3Params), '') - console.log() + rpc_doc.push('The following in3-configuration will have an impact on the result:\n\n'); + print_object(getType(def.in3Params), '', false, rpc_doc) + rpc_doc.push() } - if (def.validation) console.log('\n' + def.validation + '\n') + if (def.validation) rpc_doc.push('\n' + def.validation + '\n') if (def.returns) { if (def.returns.type) { - console.log('*Returns:* ' + (typeof def.returns.type === 'string' ? ('`' + def.returns.type + '`') : '`object`') + '\n\n' + def.returns.descr + '\n') + rpc_doc.push('*Returns:* ' + (typeof def.returns.type === 'string' ? ('`' + def.returns.type + '`') : '`object`') + '\n\n' + def.returns.descr + '\n') const pt = getType(def.returns.type) if (typeof pt === 'object') { - console.log('\nThe return value contains the following properties :\n') - print_object(pt, '') + rpc_doc.push('\nThe return value contains the following properties :\n') + print_object(pt, '', false, rpc_doc) } } else if (def.returns.alias) - console.log('*Returns:*\n\nThe Result of `' + rpc + '` is the same as ' + link(def.returns.alias) + '. See Details there.\n') + rpc_doc.push('*Returns:*\n\nThe Result of `' + rpc + '` is the same as ' + link(def.returns.alias) + '. See Details there.\n') else - console.log('*Returns:*\n\n' + (def.returns.descr || '') + '\n') + rpc_doc.push('*Returns:*\n\n' + (def.returns.descr || '') + '\n') } if (def.proof) { - console.log('*Proof:*\n\n' + (def.proof.descr || '') + '\n') + rpc_doc.push('*Proof:*\n\n' + (def.proof.descr || '') + '\n') const pt = getType(def.proof.type) if (def.proof.alias) - console.log('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') + rpc_doc.push('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') if (pt) { - console.log("This proof section contains the following properties:\n\n") - print_object(pt, '') - console.log("\n\n") + rpc_doc.push("This proof section contains the following properties:\n\n") + print_object(pt, '', false, rpc_doc) + rpc_doc.push("\n\n") } } @@ -119,21 +172,21 @@ for (const s of Object.keys(docs).sort()) { const is_json = (typeof data.result == 'object' || Array.isArray(data.result)) if (ex.in3) data.in3 = ex.in3 - console.log('*Example:*\n') - if (ex.descr) console.log('\n' + ex.descr + '\n') + rpc_doc.push('*Example:*\n') + if (ex.descr) rpc_doc.push('\n' + ex.descr + '\n') /* - console.log('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) - console.log('\n# ---- Response -----\n\n' + yaml.stringify(data)) - console.log('```\n') + rpc_doc.push('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) + rpc_doc.push('\n# ---- Response -----\n\n' + yaml.stringify(data)) + rpc_doc.push('```\n') */ - console.log('```sh\n> in3 ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) - console.log(is_json ? JSON.stringify(data.result, null, 2) : '' + data.result) - console.log('```\n') + rpc_doc.push('```sh\n> in3 ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) + rpc_doc.push(is_json ? JSON.stringify(data.result, null, 2) : '' + data.result) + rpc_doc.push('```\n') - console.log('```js\n//---- Request -----\n\n' + JSON.stringify(req, null, 2)) - console.log('\n//---- Response -----\n\n' + JSON.stringify(data, null, 2)) - console.log('```\n') + rpc_doc.push('```js\n//---- Request -----\n\n' + JSON.stringify(req, null, 2)) + rpc_doc.push('\n//---- Response -----\n\n' + JSON.stringify(data, null, 2)) + rpc_doc.push('```\n') }) z += "'" @@ -141,6 +194,11 @@ for (const s of Object.keys(docs).sort()) { } } -fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')), { encoding: 'utf8' }) +handle_config(config, '') + +fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) +fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) +fs.writeFileSync(doc_dir + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) +fs.writeFileSync('../c/src/cmd/in3/args.h', 'const char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\n const char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) From affa0d19ed46a8e92395a0ff84154916c7a0b306 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 29 Mar 2021 19:46:42 +0200 Subject: [PATCH 040/221] fix format --- c/src/cmd/in3/args.h | 36 ++++++++++++++++++------------------ scripts/build_rpc_docu.js | 4 ++-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 6bd8e6513..b8cb8b1b8 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -49,22 +49,22 @@ const char* help_args = "\ --btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ --btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n"; - const char* aliases[] = { - "c","chainId", - "f","finality", - "a","maxAttempts", - "x","experimental=true", - "p","proof", - "l","replaceLatestBlock", - "s","signatureCount", - "rc","requestCount", - "zks","zksync.provider_url", - "zka","zksync.account", - "zsk","zksync.sync_key", - "zkat","zksync.signer_type", - "zms","zksync.musig_pub_keys", - "zmu","zksync.musig_urls", - "zc2","zksync.create2", - "k","key", - "pk","pk", +const char* aliases[] = { + "c", "chainId", + "f", "finality", + "a", "maxAttempts", + "x", "experimental=true", + "p", "proof", + "l", "replaceLatestBlock", + "s", "signatureCount", + "rc", "requestCount", + "zks", "zksync.provider_url", + "zka", "zksync.account", + "zsk", "zksync.sync_key", + "zkat", "zksync.signer_type", + "zms", "zksync.musig_pub_keys", + "zmu", "zksync.musig_urls", + "zc2", "zksync.create2", + "k", "key", + "pk", "pk", NULL}; diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 49ae2f9b3..4495ca603 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -79,7 +79,7 @@ function handle_config(conf, pre) { } } - asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '","' + pre + key + (c.type == 'bool' ? '=true' : '') + '",')); + asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + pre + key + (c.type == 'bool' ? '=true' : '') + '",')); main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(6) + short_descr(c.descr)) let s = '' if (c.descr) s += '[' + short_descr(c.descr) + ']' @@ -199,6 +199,6 @@ handle_config(config, '') fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) -fs.writeFileSync('../c/src/cmd/in3/args.h', 'const char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\n const char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) +fs.writeFileSync('../c/src/cmd/in3/args.h', 'const char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) From 3983423ab59c0c8ac63da417622d004af59107c0 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 29 Mar 2021 21:20:12 +0200 Subject: [PATCH 041/221] startbin3.yml --- c/src/cmd/in3/in3.yml | 123 ++++++++++++++++++++++++++++++++++ c/src/nodeselect/full/rpc.yml | 1 + 2 files changed, 124 insertions(+) create mode 100644 c/src/cmd/in3/in3.yml diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml new file mode 100644 index 000000000..749744058 --- /dev/null +++ b/c/src/cmd/in3/in3.yml @@ -0,0 +1,123 @@ +aliases: + nostats : ns + 'proof=none' : np + eth : e + block : b + to : to + from: from + data : d + gas_price : gp + gas : gas + path : path + sigtype : st + password: pwd + value : value + wait : w + json: json + hex: h + keepin3 : kin3 + debug : debug + quiet : q + human : h + test-request: tr + test-health-request: thr + multisig : ms + signatures : sigs + response-in : ri + response-out : ro + file-in: fi + file-out: fo + nodelist: nl + bootnodes: bn + onlysign: os + version: v + help: h + +config: + nostats : no stats if set requests will not be part of the official metrics and considered a service request + eth : converts the result (as wei) to ether. + port : if specified it will run as http-server listening to the given port. + am : only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed. All other will be rejected. + block: the blocknumber to use when making calls. could be either latest (default),earliest or a hexnumbner + to: the target address of the call + from : the sender of a call or tx (only needed if no signer is registered) + data : the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin. + gas_price: 'the gas price to use when sending transactions. (default: use eth_gasPrice)' + gas : 'the gas limit to use when sending transactions. (default: 100000)' + path : 'the HD wallet derivation path . We can pass in simplified way as hex string i.e [44,60,00,00,00] => 0x2c3c000000' + sigtype: 'the type of the signature data : eth_sign (use the prefix and hash it), raw (hash the raw data), hash (use the already hashed data). Default: raw' + password: password to unlock the key + value : 'the value to send when sending a transaction. can be hexvalue or a float/integer with the suffix eth or wei like 1.8eth (default: 0)' + wait: if given, instead returning the transaction, it will wait until the transaction is mined and return the transactionreceipt. + json : if given the result will be returned as json, which is especially important for eth_call results with complex structres. + hex : if given the result will be returned as hex. + keepin3 : if specified, the response including in3-section is returned + debug : if given incubed will output debug information when executing. + quiet: quiet. no additional output. + human : human readable, which removes the json -structure and oly displays the values. + test-request: runs test request when showing in3_weights + test-health-request: runs test request including health-check when showing in3_weights + multisig : adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) + signatures : add additional signatures, which will be useds when sending through a multisig! + response-in: read response from stdin + response-out: write raw response to stdout + file-in: reads a prerecorded request from the filepath and executes it with the recorded data. (great for debugging) + file-out: records a request and writes the reproducable data in a file (including all cache-data, timestamps ...) + nodelist: a coma seperated list of urls (or address:url) to be used as fixed nodelist + bootnodes: a coma seperated list of urls (or address:url) to be used as boot nodes + onlysign: only sign, don't send the raw Transaction + version: displays the version + help: displays this help message + +As method, the following can be used: + +-method + all official supported JSON-RPC-Method may be used. + +send ...args + based on the -to, -value and -pk a transaction is build, signed and send. + if there is another argument after send, this would be taken as a function-signature of the smart contract followed by optional argument of the function. + +call ...args + uses eth_call to call a function. Following the call argument the function-signature and its arguments must follow. + +in3_nodeList + returns the nodeList of the Incubed NodeRegistry as json. + +in3_sign + requests a node to sign. in order to specify the signer, you need to pass the url with -c + +ipfs_get + requests and verifies the content for a given ipfs-hash and write the content to stdout + +ipfs_put + reads a content from stdin and pushes to the ipfs-network. it write the ipfs-hash to stdout. + +in3_stats + returns the stats of a node. unless you specify the node with -c it will pick a random node. + +abi_encode ...args + encodes the arguments as described in the method signature using ABI-Encoding + +abi_decode data + decodes the data based on the signature. + +pk2address + extracts the public address from a private key + +pk2public + extracts the public key from a private key + +ecrecover + extracts the address and public key from a signature + +key + reads the private key from JSON-Keystore file and returns the private key. + +in3_weights + list all current weights and stats + +in3_ens + resolves a ens-domain. field can be addr(deault), owner, resolver or hash +\n", + diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 2b5384dcf..644d4b932 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -23,6 +23,7 @@ in3: optional: true example: true default: true + cmd: bw useHttp: descr: if true the client will try to use http instead of https. From cb07bdc1dfc77c859bdde517e9b7f61b351b39f8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 29 Mar 2021 23:26:04 +0200 Subject: [PATCH 042/221] generate help-page --- c/src/cmd/in3/args.h | 201 ++++++++++++++++------ c/src/cmd/in3/in3.yml | 340 ++++++++++++++++++++++++-------------- c/src/cmd/in3/main.c | 106 +----------- scripts/_in3.sh | 69 ++++++++ scripts/build_rpc_docu.js | 19 ++- 5 files changed, 455 insertions(+), 280 deletions(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index b8cb8b1b8..2346f0f0a 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -1,53 +1,121 @@ const char* help_args = "\ ---chainId -c the chainId or the name of a known chain\n\ ---finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ ---includeCode if true, the request should include the codes of all accounts\n\ ---maxAttempts -a max number of attempts in case a response is rejected\n\ ---keepIn3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ ---useBinary if true the client will use binary format\n\ ---experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ ---timeout specifies the number of milliseconds before the request times out\n\ ---proof -p if true the nodes should send a proof of the response\n\ ---replaceLatestBlock -l if specified, the blocknumber *latest* will be replaced by blockNumber- specified value\n\ ---autoUpdateList if true the nodelist will be automaticly updated if the lastBlock is newer\n\ ---signatureCount -s number of signatures requested in order to verify the blockhash\n\ ---bootWeights if true, the first request (updating the nodelist) will also fetch the current health status and use...\n\ ---useHttp if true the client will try to use http instead of https\n\ ---minDeposit min stake of the server\n\ ---nodeProps used to identify the capabilities of the node\n\ ---requestCount -rc the number of request send in parallel when getting an answer\n\ ---rpc url of one or more direct rpc-endpoints to use\n\ ---nodes defining the nodelist\n\ ---nodes.contract address of the registry contract\n\ ---nodes.whiteListContract address of the whiteList contract\n\ ---nodes.whiteList manual whitelist\n\ ---nodes.registryId identifier of the registry\n\ ---nodes.needsUpdate if set, the nodeList will be updated before next request\n\ ---nodes.avgBlockTime average block time (seconds) for this chain\n\ ---nodes.verifiedHashes if the client sends an array of blockhashes the server will not deliver any signatures or blockheade...\n\ ---nodes.verifiedHashes.block block number\n\ ---nodes.verifiedHashes.hash verified hash corresponding to block number\n\ ---nodes.nodeList manual nodeList\n\ ---nodes.nodeList.url URL of the node\n\ ---nodes.nodeList.address address of the node\n\ ---nodes.nodeList.props used to identify the capabilities of the node (defaults to 0xFFFF)\n\ ---zksync configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per defaul...\n\ ---zksync.provider_url -zks url of the zksync-server (if not defined it will be choosen depending on the chain)\n\ ---zksync.account -zka the account to be used\n\ ---zksync.sync_key -zsk the seed used to generate the sync_key\n\ ---zksync.main_contract address of the main contract- If not specified it will be taken from the server\n\ ---zksync.signer_type -zkat type of the account\n\ ---zksync.musig_pub_keys -zms concatenated packed public keys (32byte) of the musig signers\n\ ---zksync.musig_urls -zmu a array of strings with urls based on the `musig_pub_keys`\n\ ---zksync.create2 -zc2 create2-arguments for sign_type `create2`\n\ ---zksync.create2.creator The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )\n\ ---zksync.create2.saltarg a salt-argument, which will be added to the pubkeyhash and create the create2-salt\n\ ---zksync.create2.codehash the hash of the actual deploy-tx including the constructor-arguments\n\ ---key -k the client key to sign requests\n\ ---pk -pk registers raw private keys as signers for transactions\n\ ---btc configure the Bitcoin verification\n\ ---btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ ---btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n"; +--chainId -c the chainId or the name of a known chain\n\ +--finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ +--includeCode if true, the request should include the codes of all accounts\n\ +--maxAttempts -a max number of attempts in case a response is rejected\n\ +--keepIn3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ +--useBinary if true the client will use binary format\n\ +--experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ +--timeout specifies the number of milliseconds before the request times out\n\ +--proof -p if true the nodes should send a proof of the response\n\ +--replaceLatestBlock -l if specified, the blocknumber *latest* will be replaced by blockNumber- specified value\n\ +--autoUpdateList if true the nodelist will be automaticly updated if the lastBlock is newer\n\ +--signatureCount -s number of signatures requested in order to verify the blockhash\n\ +--bootWeights -bw if true, the first request (updating the nodelist) will also fetch the current health status and use...\n\ +--useHttp if true the client will try to use http instead of https\n\ +--minDeposit min stake of the server\n\ +--nodeProps used to identify the capabilities of the node\n\ +--requestCount -rc the number of request send in parallel when getting an answer\n\ +--rpc url of one or more direct rpc-endpoints to use\n\ +--nodes defining the nodelist\n\ +--nodes.contract address of the registry contract\n\ +--nodes.whiteListContract address of the whiteList contract\n\ +--nodes.whiteList manual whitelist\n\ +--nodes.registryId identifier of the registry\n\ +--nodes.needsUpdate if set, the nodeList will be updated before next request\n\ +--nodes.avgBlockTime average block time (seconds) for this chain\n\ +--nodes.verifiedHashes if the client sends an array of blockhashes the server will not deliver any signatures or blockheade...\n\ +--nodes.verifiedHashes.block block number\n\ +--nodes.verifiedHashes.hash verified hash corresponding to block number\n\ +--nodes.nodeList manual nodeList\n\ +--nodes.nodeList.url URL of the node\n\ +--nodes.nodeList.address address of the node\n\ +--nodes.nodeList.props used to identify the capabilities of the node (defaults to 0xFFFF)\n\ +--zksync configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per defaul...\n\ +--zksync.provider_url -zks url of the zksync-server (if not defined it will be choosen depending on the chain)\n\ +--zksync.account -zka the account to be used\n\ +--zksync.sync_key -zsk the seed used to generate the sync_key\n\ +--zksync.main_contract address of the main contract- If not specified it will be taken from the server\n\ +--zksync.signer_type -zkat type of the account\n\ +--zksync.musig_pub_keys -zms concatenated packed public keys (32byte) of the musig signers\n\ +--zksync.musig_urls -zmu a array of strings with urls based on the `musig_pub_keys`\n\ +--zksync.create2 -zc2 create2-arguments for sign_type `create2`\n\ +--zksync.create2.creator The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )\n\ +--zksync.create2.saltarg a salt-argument, which will be added to the pubkeyhash and create the create2-salt\n\ +--zksync.create2.codehash the hash of the actual deploy-tx including the constructor-arguments\n\ +--key -k the client key to sign requests\n\ +--pk -pk registers raw private keys as signers for transactions\n\ +--btc configure the Bitcoin verification\n\ +--btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ +--btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n\ +--nostats -ns no stats if set requests will not be part of the official metrics and considered a service request\n\ +--eth -e converts the result (as wei) to ether\n\ +--port -port if specified it will run as http-server listening to the given port\n\ +--allowed-methods -am only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed\n\ +--block -b the blocknumber to use when making calls\n\ +--to -to the target address of the call\n\ +--from -from the sender of a call or tx (only needed if no signer is registered)\n\ +--data -d the data for a transaction\n\ +--gas_price -gp the gas price to use when sending transactions\n\ +--gas -gas the gas limit to use when sending transactions\n\ +--path -path the HD wallet derivation path \n\ +--sigtype -ns the type of the signature data\n\ +--password -pwd password to unlock the key\n\ +--value -value the value to send when sending a transaction\n\ +--wait -w if given, instead returning the transaction, it will wait until the transaction is mined and return ...\n\ +--json -json if given the result will be returned as json, which is especially important for eth_call results wit...\n\ +--hex -hex if given the result will be returned as hex\n\ +--keepin3 -kin3 if specified, the response including in3-section is returned\n\ +--debug -debug if given incubed will output debug information when executing\n\ +--quiet -q quiet\n\ +--human -h human readable, which removes the json -structure and oly displays the values\n\ +--test-request -tr runs test request when showing in3_weights\n\ +--test-health-request -thr runs test request including health-check when showing in3_weights\n\ +--multisig -ms adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...\n\ +--signatures -sigs add additional signatures, which will be useds when sending through a multisig!\n\ +--response-in -ri read response from stdin\n\ +--response-out -ro write raw response to stdout\n\ +--file-in -fi reads a prerecorded request from the filepath and executes it with the recorded data\n\ +--file-out -fo records a request and writes the reproducable data in a file (including all cache-data, timestamps \n\ +--nodelist -nl a coma seperated list of urls (or address:url) to be used as fixed nodelist\n\ +--bootnodes -bn a coma seperated list of urls (or address:url) to be used as boot nodes\n\ +--onlysign -os only sign, don't send the raw Transaction\n\ +--version -v displays the version\n\ +--help -h displays this help message\n\ +\n\ +In addition to the documented rpc-methods, those methods are also supported:\n\ +\n\ +send ...args\n\ + based on the -to, -value and -pk a transaction is build, signed and send.\n\ + if there is another argument after send, this would be taken as a function-signature of the smart contract followed by optional argument of the function.\n\ + \n\ +call ...args\n\ + uses eth_call to call a function. Following the call argument the function-signature and its arguments must follow.\n\ + \n\ +in3_nodeList returns the nodeList of the Incubed NodeRegistry as json.\n\ +in3_sign \n\ + requests a node to sign. in order to specify the signer, you need to pass the url with -c\n\ + \n\ +abi_encode ...args\n\ + encodes the arguments as described in the method signature using ABI-Encoding\n\ + \n\ +abi_decode data\n\ + decodes the data based on the signature.\n\ + \n\ +pk2address \n\ + extracts the public address from a private key\n\ + \n\ +pk2public \n\ + extracts the public key from a private key\n\ + \n\ +ecrecover \n\ + extracts the address and public key from a signature\n\ + \n\ +key \n\ + reads the private key from JSON-Keystore file and returns the private key.\n\ + \n\ +in3_weights list all current weights and stats\n\ + \n"; const char* aliases[] = { "c", "chainId", @@ -57,6 +125,7 @@ const char* aliases[] = { "p", "proof", "l", "replaceLatestBlock", "s", "signatureCount", + "bw", "bootWeights=true", "rc", "requestCount", "zks", "zksync.provider_url", "zka", "zksync.account", @@ -67,4 +136,38 @@ const char* aliases[] = { "zc2", "zksync.create2", "k", "key", "pk", "pk", + "ns", "nostats=true", + "e", "eth=true", + "port", "port", + "am", "allowed-methods", + "b", "block", + "to", "to", + "from", "from", + "d", "data", + "gp", "gas_price", + "gas", "gas", + "path", "path", + "ns", "sigtype", + "pwd", "password", + "value", "value", + "w", "wait=true", + "json", "json=true", + "hex", "hex=true", + "kin3", "keepin3=true", + "debug", "debug=true", + "q", "quiet=true", + "h", "human=true", + "tr", "test-request=true", + "thr", "test-health-request=true", + "ms", "multisig", + "sigs", "signatures", + "ri", "response-in", + "ro", "response-out", + "fi", "file-in", + "fo", "file-out", + "nl", "nodelist", + "bn", "bootnodes", + "os", "onlysign=true", + "v", "version=true", + "h", "help=true", NULL}; diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml index 749744058..6f82ce6e9 100644 --- a/c/src/cmd/in3/in3.yml +++ b/c/src/cmd/in3/in3.yml @@ -1,123 +1,219 @@ -aliases: - nostats : ns - 'proof=none' : np - eth : e - block : b - to : to - from: from - data : d - gas_price : gp - gas : gas - path : path - sigtype : st - password: pwd - value : value - wait : w - json: json - hex: h - keepin3 : kin3 - debug : debug - quiet : q - human : h - test-request: tr - test-health-request: thr - multisig : ms - signatures : sigs - response-in : ri - response-out : ro - file-in: fi - file-out: fo - nodelist: nl - bootnodes: bn - onlysign: os - version: v - help: h - config: - nostats : no stats if set requests will not be part of the official metrics and considered a service request - eth : converts the result (as wei) to ether. - port : if specified it will run as http-server listening to the given port. - am : only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed. All other will be rejected. - block: the blocknumber to use when making calls. could be either latest (default),earliest or a hexnumbner - to: the target address of the call - from : the sender of a call or tx (only needed if no signer is registered) - data : the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin. - gas_price: 'the gas price to use when sending transactions. (default: use eth_gasPrice)' - gas : 'the gas limit to use when sending transactions. (default: 100000)' - path : 'the HD wallet derivation path . We can pass in simplified way as hex string i.e [44,60,00,00,00] => 0x2c3c000000' - sigtype: 'the type of the signature data : eth_sign (use the prefix and hash it), raw (hash the raw data), hash (use the already hashed data). Default: raw' - password: password to unlock the key - value : 'the value to send when sending a transaction. can be hexvalue or a float/integer with the suffix eth or wei like 1.8eth (default: 0)' - wait: if given, instead returning the transaction, it will wait until the transaction is mined and return the transactionreceipt. - json : if given the result will be returned as json, which is especially important for eth_call results with complex structres. - hex : if given the result will be returned as hex. - keepin3 : if specified, the response including in3-section is returned - debug : if given incubed will output debug information when executing. - quiet: quiet. no additional output. - human : human readable, which removes the json -structure and oly displays the values. - test-request: runs test request when showing in3_weights - test-health-request: runs test request including health-check when showing in3_weights - multisig : adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) - signatures : add additional signatures, which will be useds when sending through a multisig! - response-in: read response from stdin - response-out: write raw response to stdout - file-in: reads a prerecorded request from the filepath and executes it with the recorded data. (great for debugging) - file-out: records a request and writes the reproducable data in a file (including all cache-data, timestamps ...) - nodelist: a coma seperated list of urls (or address:url) to be used as fixed nodelist - bootnodes: a coma seperated list of urls (or address:url) to be used as boot nodes - onlysign: only sign, don't send the raw Transaction - version: displays the version - help: displays this help message - -As method, the following can be used: - --method - all official supported JSON-RPC-Method may be used. - -send ...args - based on the -to, -value and -pk a transaction is build, signed and send. - if there is another argument after send, this would be taken as a function-signature of the smart contract followed by optional argument of the function. - -call ...args - uses eth_call to call a function. Following the call argument the function-signature and its arguments must follow. - -in3_nodeList - returns the nodeList of the Incubed NodeRegistry as json. - -in3_sign - requests a node to sign. in order to specify the signer, you need to pass the url with -c - -ipfs_get - requests and verifies the content for a given ipfs-hash and write the content to stdout - -ipfs_put - reads a content from stdin and pushes to the ipfs-network. it write the ipfs-hash to stdout. - -in3_stats - returns the stats of a node. unless you specify the node with -c it will pick a random node. - -abi_encode ...args - encodes the arguments as described in the method signature using ABI-Encoding - -abi_decode data - decodes the data based on the signature. - -pk2address - extracts the public address from a private key - -pk2public - extracts the public key from a private key - -ecrecover - extracts the address and public key from a signature - -key - reads the private key from JSON-Keystore file and returns the private key. - -in3_weights - list all current weights and stats - -in3_ens - resolves a ens-domain. field can be addr(deault), owner, resolver or hash -\n", - + nostats : + descr: no stats if set requests will not be part of the official metrics and considered a service request + cmd: ns + type: bool + example: true + eth : + cmd: e + type: bool + descr: converts the result (as wei) to ether. + example: true + port : + cmd: port + type: uint + descr: if specified it will run as http-server listening to the given port. + example: 8545 + allowed-methods : + cmd: am + type: string + descr: only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed. All other will be rejected. + example: eth_sign,eth_blockNumber + block: + cmd: b + type: uint + descr: the blocknumber to use when making calls. could be either latest (default),earliest or a hexnumbner + example: latest + to: + cmd: to + type: address + descr: the target address of the call + example: '0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6' + from : + cmd: from + type: address + descr: the sender of a call or tx (only needed if no signer is registered) + example: '0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6' + data : + cmd: d + type: bytes + descr: the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin. + example: '0x7d1c101' + gas_price: + cmd: gp + type: uint + descr: 'the gas price to use when sending transactions. (default: use eth_gasPrice)' + example: 1000000000000 + gas : + cmd: gas + type: uint + descr: 'the gas limit to use when sending transactions. (default: 100000)' + example: 100000 + path : + cmd: path + type: string + descr: 'the HD wallet derivation path . We can pass in simplified way as hex string i.e [44,60,00,00,00] => 0x2c3c000000' + example: '0x2c3c000000' + sigtype: + cmd: ns + type: string + enum: + raw: hash the raw data + hash: use the already hashed data + eth_sign: use the prefix and hash it + default: raw + descr: the type of the signature data. + example: hash + password: + cmd: pwd + type: string + descr: password to unlock the key + example: MYPASSWORD + value : + cmd: value + type: uint + descr: 'the value to send when sending a transaction. can be hexvalue or a float/integer with the suffix eth or wei like 1.8eth (default: 0)' + example: '0.2eth' + wait: + cmd: w + type: bool + descr: if given, instead returning the transaction, it will wait until the transaction is mined and return the transactionreceipt. + example: true + json : + cmd: json + type: bool + descr: if given the result will be returned as json, which is especially important for eth_call results with complex structres. + example: true + hex : + cmd: hex + type: bool + descr: if given the result will be returned as hex. + example: true + keepin3 : + cmd: kin3 + type: bool + descr: if specified, the response including in3-section is returned + example: true + debug : + cmd: debug + type: bool + descr: if given incubed will output debug information when executing. + example: true + quiet: + cmd: q + type: bool + descr: quiet. no additional output. + example: true + human : + cmd: h + type: bool + descr: human readable, which removes the json -structure and oly displays the values. + example: true + test-request: + cmd: tr + type: bool + descr: runs test request when showing in3_weights + example: true + test-health-request: + cmd: thr + type: bool + descr: runs test request including health-check when showing in3_weights + example: true + multisig : + cmd: ms + type: address + descr: adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) + example: '0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6' + signatures : + cmd: sigs + type: bytes + descr: add additional signatures, which will be useds when sending through a multisig! + example: 0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6ab00f111c32258f3a53bd1dead143dd5d7eae3737c7b0f21843afcdd27a1b8f0 + response-in: + cmd: ri + type: string + descr: read response from stdin + example: response.json + response-out: + cmd: ro + type: string + descr: write raw response to stdout + example: response.json + file-in: + cmd: fi + type: string + descr: reads a prerecorded request from the filepath and executes it with the recorded data. (great for debugging) + example: record.txt + file-out: + cmd: fo + type: string + descr: records a request and writes the reproducable data in a file (including all cache-data, timestamps ...) + example: record.txt + nodelist: + cmd: nl + type: string + descr: a coma seperated list of urls (or address:url) to be used as fixed nodelist + example: 'https://in3-v2.slock.it/mainnet/nd-1,https://mainnet.incubed.net' + bootnodes: + cmd: bn + type: string + descr: a coma seperated list of urls (or address:url) to be used as boot nodes + example: 'https://in3-v2.slock.it/mainnet/nd-1,https://mainnet.incubed.net' + onlysign: + cmd: os + type: bool + descr: only sign, don't send the raw Transaction + example: true + version: + cmd: v + type: bool + descr: displays the version + example: true + help: + cmd: h + type: bool + descr: displays this help message + example: true + +rpc: + send: | + ...args + based on the -to, -value and -pk a transaction is build, signed and send. + if there is another argument after send, this would be taken as a function-signature of the smart contract followed by optional argument of the function. + + call: | + ...args + uses eth_call to call a function. Following the call argument the function-signature and its arguments must follow. + + in3_nodeList: returns the nodeList of the Incubed NodeRegistry as json. + + in3_sign: | + + requests a node to sign. in order to specify the signer, you need to pass the url with -c + + abi_encode: | + ...args + encodes the arguments as described in the method signature using ABI-Encoding + + abi_decode: | + data + decodes the data based on the signature. + + pk2address: | + + extracts the public address from a private key + + pk2public: | + + extracts the public key from a private key + + ecrecover: | + + extracts the address and public key from a signature + + key: | + + reads the private key from JSON-Keystore file and returns the private key. + + in3_weights: | + list all current weights and stats diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index dd65a3c65..2df9bc024 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -92,111 +92,7 @@ void show_help(char* name) { recorder_print(0, "Usage: %s method ... \n\ \n\ -%s\n\ --ns no stats if set requests will not be part of the official metrics and considered a service request\n\ --np short for -p none\n\ --eth converts the result (as wei) to ether.\n\ --l, -latest replaces \"latest\" with latest BlockNumber - the number of blocks given.\n\ --s, -signs number of signatures to use when verifying.\n\ --f finality : number of blocks on top of the current one.\n\ --port if specified it will run as http-server listening to the given port.\n\ --am only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed. All other will be rejected.\n\ --b, -block the blocknumber to use when making calls. could be either latest (default),earliest or a hexnumbner\n\ --to the target address of the call\n\ --from the sender of a call or tx (only needed if no signer is registered)\n\ --d, -data the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin.\n\ --gp,-gas_price the gas price to use when sending transactions. (default: use eth_gasPrice) \n\ --gas the gas limit to use when sending transactions. (default: 100000) \n\ --pk the private key as raw as keystorefile \n\ --path the HD wallet derivation path . We can pass in simplified way as hex string i.e [44,60,00,00,00] => 0x2c3c000000 \n\ --st, -sigtype the type of the signature data : eth_sign (use the prefix and hash it), raw (hash the raw data), hash (use the already hashed data). Default: raw \n\ --pwd password to unlock the key \n\ --value the value to send when sending a transaction. can be hexvalue or a float/integer with the suffix eth or wei like 1.8eth (default: 0)\n\ --w, -wait if given, instead returning the transaction, it will wait until the transaction is mined and return the transactionreceipt.\n\ --json if given the result will be returned as json, which is especially important for eth_call results with complex structres.\n\ --hex if given the result will be returned as hex.\n\ --kin3 if kin3 is specified, the response including in3-section is returned\n\ --bw initialize with weights from boot nodes.\n\ --debug if given incubed will output debug information when executing. \n\ --k 32bytes raw private key to sign requests.\n\ --q quit. no additional output. \n\ --h human readable, which removes the json -structure and oly displays the values.\n\ --tr runs test request when showing in3_weights \n\ --thr runs test request including health-check when showing in3_weights \n\ --ms adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) \n\ --sigs add additional signatures, which will be useds when sending through a multisig! \n\ --ri read response from stdin \n\ --ro write raw response to stdout \n\ --fi reads a prerecorded request from the filepath and executes it with the recorded data. (great for debugging) \n\ --fo records a request and writes the reproducable data in a file (including all cache-data, timestamps ...) \n\ --nl a coma seperated list of urls (or address:url) to be used as fixed nodelist\n\ --bn a coma seperated list of urls (or address:url) to be used as boot nodes\n\ --zks zksync server to use\n\ --zkss zksync signatures to pass along when signing\n\ --zka zksync account to use\n\ --zkat zksync account type could be one of 'pk'(default), 'contract' or 'create2'\n\ --zsk zksync signer seed (if not set this key will be derrived from account unless create2)\n\ --zc2 zksync create2 arguments in the form ::. if set the account type is also changed to create2\n\ --zms public keys of a musig schnorr signatures to sign with\n\ --zmu url for signing service matching the first remote public key\n\ --zvpm method for calling to verify the proof\n\ --zcpm method for calling to create the proof\n\ --os only sign, don't send the raw Transaction \n\ --x support experimental features \n\ --version displays the version \n\ --help displays this help message \n\ -\n\ -As method, the following can be used:\n\ -\n\ --method\n\ - all official supported JSON-RPC-Method may be used.\n\ -\n\ -send ...args\n\ - based on the -to, -value and -pk a transaction is build, signed and send. \n\ - if there is another argument after send, this would be taken as a function-signature of the smart contract followed by optional argument of the function.\n\ -\n\ -call ...args\n\ - uses eth_call to call a function. Following the call argument the function-signature and its arguments must follow. \n\ -\n\ -in3_nodeList\n\ - returns the nodeList of the Incubed NodeRegistry as json.\n\ -\n\ -in3_sign \n\ - requests a node to sign. in order to specify the signer, you need to pass the url with -c\n\ -\n\ -ipfs_get \n\ - requests and verifies the content for a given ipfs-hash and write the content to stdout\n\ -\n\ -ipfs_put\n\ - reads a content from stdin and pushes to the ipfs-network. it write the ipfs-hash to stdout.\n\ -\n\ -in3_stats\n\ - returns the stats of a node. unless you specify the node with -c it will pick a random node.\n\ -\n\ -abi_encode ...args\n\ - encodes the arguments as described in the method signature using ABI-Encoding\n\ -\n\ -abi_decode data\n\ - decodes the data based on the signature.\n\ -\n\ -pk2address \n\ - extracts the public address from a private key\n\ -\n\ -pk2public \n\ - extracts the public key from a private key\n\ -\n\ -ecrecover \n\ - extracts the address and public key from a signature\n\ -\n\ -key \n\ - reads the private key from JSON-Keystore file and returns the private key.\n\ -\n\ -in3_weights\n\ - list all current weights and stats\n\ -\n\ -in3_ens \n\ - resolves a ens-domain. field can be addr(deault), owner, resolver or hash\n\ -\n", +%s", name, help_args); } _Noreturn static void die(char* msg) { diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 487315971..04741d914 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -112,6 +112,7 @@ args=( '--signatureCount=[number of signatures requested in order to verify the blockhash]:signatureCount:()' '-s[number of signatures requested in order to verify the blockhash]:signatureCount:()' '--bootWeights[if true, the first request (updating the nodelist) will also fetch the current health status and use...]' +'-bw[if true, the first request (updating the nodelist) will also fetch the current health status and use...]' '--useHttp[if true the client will try to use http instead of https]' '--minDeposit=[min stake of the server]:minDeposit:()' '--nodeProps=[used to identify the capabilities of the node]:nodeProps:()' @@ -151,6 +152,74 @@ args=( '-pk[registers raw private keys as signers for transactions]:pk:()' '--btc.maxDAP=[max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets]:maxDAP:()' '--btc.maxDiff=[max increase (in percent) of the difference between targets when accepting new targets]:maxDiff:()' +'--nostats[no stats if set requests will not be part of the official metrics and considered a service request]' +'-ns[no stats if set requests will not be part of the official metrics and considered a service request]' +'--eth[converts the result (as wei) to ether]' +'-e[converts the result (as wei) to ether]' +'--port=[if specified it will run as http-server listening to the given port]:port:()' +'-port[if specified it will run as http-server listening to the given port]:port:()' +'--allowed-methods=[only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed]:allowed-methods:()' +'-am[only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed]:allowed-methods:()' +'--block=[the blocknumber to use when making calls]:block:()' +'-b[the blocknumber to use when making calls]:block:()' +'--to=[the target address of the call]:to:()' +'-to[the target address of the call]:to:()' +'--from=[the sender of a call or tx (only needed if no signer is registered)]:from:()' +'-from[the sender of a call or tx (only needed if no signer is registered)]:from:()' +'--data=[the data for a transaction]:data:()' +'-d[the data for a transaction]:data:()' +'--gas_price=[the gas price to use when sending transactions]:gas_price:()' +'-gp[the gas price to use when sending transactions]:gas_price:()' +'--gas=[the gas limit to use when sending transactions]:gas:()' +'-gas[the gas limit to use when sending transactions]:gas:()' +'--path=[the HD wallet derivation path ]:path:()' +'-path[the HD wallet derivation path ]:path:()' +'--sigtype=[the type of the signature data]:sigtype:(raw hash eth_sign)' +'-ns[the type of the signature data]:sigtype:(raw hash eth_sign)' +'--password=[password to unlock the key]:password:()' +'-pwd[password to unlock the key]:password:()' +'--value=[the value to send when sending a transaction]:value:()' +'-value[the value to send when sending a transaction]:value:()' +'--wait[if given, instead returning the transaction, it will wait until the transaction is mined and return ...]' +'-w[if given, instead returning the transaction, it will wait until the transaction is mined and return ...]' +'--json[if given the result will be returned as json, which is especially important for eth_call results wit...]' +'-json[if given the result will be returned as json, which is especially important for eth_call results wit...]' +'--hex[if given the result will be returned as hex]' +'-hex[if given the result will be returned as hex]' +'--keepin3[if specified, the response including in3-section is returned]' +'-kin3[if specified, the response including in3-section is returned]' +'--debug[if given incubed will output debug information when executing]' +'-debug[if given incubed will output debug information when executing]' +'--quiet[quiet]' +'-q[quiet]' +'--human[human readable, which removes the json -structure and oly displays the values]' +'-h[human readable, which removes the json -structure and oly displays the values]' +'--test-request[runs test request when showing in3_weights]' +'-tr[runs test request when showing in3_weights]' +'--test-health-request[runs test request including health-check when showing in3_weights]' +'-thr[runs test request including health-check when showing in3_weights]' +'--multisig=[adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...]:multisig:()' +'-ms[adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...]:multisig:()' +'--signatures=[add additional signatures, which will be useds when sending through a multisig!]:signatures:()' +'-sigs[add additional signatures, which will be useds when sending through a multisig!]:signatures:()' +'--response-in=[read response from stdin]:response-in:()' +'-ri[read response from stdin]:response-in:()' +'--response-out=[write raw response to stdout]:response-out:()' +'-ro[write raw response to stdout]:response-out:()' +'--file-in=[reads a prerecorded request from the filepath and executes it with the recorded data]:file-in:()' +'-fi[reads a prerecorded request from the filepath and executes it with the recorded data]:file-in:()' +'--file-out=[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file-out:()' +'-fo[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file-out:()' +'--nodelist=[a coma seperated list of urls (or address:url) to be used as fixed nodelist]:nodelist:()' +'-nl[a coma seperated list of urls (or address:url) to be used as fixed nodelist]:nodelist:()' +'--bootnodes=[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' +'-bn[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' +'--onlysign[only sign, don't send the raw Transaction]' +'-os[only sign, don't send the raw Transaction]' +'--version[displays the version]' +'-v[displays the version]' +'--help[displays this help message]' +'-h[displays this help message]' '-st[the type of the signature data]:st:(eth_sign raw hash)' '-pwd[password to unlock the key]:pwd:()' '-np[short for -p none]' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 4495ca603..64f297b45 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -1,6 +1,7 @@ const yaml = require('../wasm/test/node_modules/yaml') const fs = require('fs') const doc_dir = process.argv[process.argv.length - 1] +const main_conf = yaml.parse(fs.readFileSync('../c/src/cmd/in3/in3.yml', 'utf-8')) const rpc_doc = [] const config_doc = [] @@ -51,11 +52,12 @@ function print_object(def, pad, useNum, doc) { } } -function handle_config(conf, pre) { +function handle_config(conf, pre, title, descr) { + if (title) config_doc.push('\n## ' + title + '\n') for (const key of Object.keys(conf)) { const c = conf[key] if (!pre) { - let s = '\n## ' + key + '\n\n' + c.descr + let s = '\n' + (title ? '#' : '') + '## ' + key + '\n\n' + c.descr if (c.optional) s += ' *This config is optional.*' if (c.default) s += ' (default: `' + JSON.stringify(c.default) + '`)' if (c.type) s += '\n\n Type: `' + (typeof c.type === 'string' ? c.type : 'object') + '`' @@ -74,13 +76,14 @@ function handle_config(conf, pre) { else config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') config_doc.push('```\n') - config_doc.push('```js\nconst in3 = new IN3(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') + if (!title) + config_doc.push('```js\nconst in3 = new IN3(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') }) } } asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + pre + key + (c.type == 'bool' ? '=true' : '') + '",')); - main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(6) + short_descr(c.descr)) + main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(7) + short_descr(c.descr)) let s = '' if (c.descr) s += '[' + short_descr(c.descr) + ']' if (c.type != 'bool') @@ -195,6 +198,14 @@ for (const s of Object.keys(docs).sort()) { } handle_config(config, '') +handle_config(main_conf.config, '', 'cmdline options\n\nThose special options are used in the comandline client to pass additional options.\n') +main_help.push('') +main_help.push('In addition to the documented rpc-methods, those methods are also supported:') +main_help.push('') +Object.keys(main_conf.rpc).forEach(k => { + (k + ' ' + main_conf.rpc[k]).split("\n").map(_ => _.trim()).map((_, i) => i ? ' ' + _ : _) + .forEach(l => main_help.push(l)) +}) fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) From 95e7a47447084d98260aacb68b9f76dabff01d40 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:00:27 +0200 Subject: [PATCH 043/221] fix rpc.yml --- c/src/cmd/in3/args.h | 33 ++++++++++++++---------- c/src/cmd/in3/in3.yml | 54 +++++++++++++++++++++++++++------------ c/src/core/client/rpc.yml | 9 +++++++ scripts/_in3.sh | 31 +++++++++++++--------- scripts/build_rpc_docu.js | 2 +- 5 files changed, 87 insertions(+), 42 deletions(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 2346f0f0a..3c17350e8 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -3,7 +3,7 @@ const char* help_args = "\ --finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ --includeCode if true, the request should include the codes of all accounts\n\ --maxAttempts -a max number of attempts in case a response is rejected\n\ ---keepIn3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ +--keepIn3 -kin3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ --useBinary if true the client will use binary format\n\ --experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ --timeout specifies the number of milliseconds before the request times out\n\ @@ -49,6 +49,7 @@ const char* help_args = "\ --btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ --btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n\ --nostats -ns no stats if set requests will not be part of the official metrics and considered a service request\n\ +--clearCache -ccacheclears the cache before performing any operation\n\ --eth -e converts the result (as wei) to ether\n\ --port -port if specified it will run as http-server listening to the given port\n\ --allowed-methods -am only works if port is specified and declares a comma-seperated list of rpc-methods which are allowed\n\ @@ -58,6 +59,8 @@ const char* help_args = "\ --data -d the data for a transaction\n\ --gas_price -gp the gas price to use when sending transactions\n\ --gas -gas the gas limit to use when sending transactions\n\ +--nonce -nonce the nonce\n\ +--test -test creates a new json-test written to stdout with the name as specified\n\ --path -path the HD wallet derivation path \n\ --sigtype -ns the type of the signature data\n\ --password -pwd password to unlock the key\n\ @@ -65,21 +68,21 @@ const char* help_args = "\ --wait -w if given, instead returning the transaction, it will wait until the transaction is mined and return ...\n\ --json -json if given the result will be returned as json, which is especially important for eth_call results wit...\n\ --hex -hex if given the result will be returned as hex\n\ ---keepin3 -kin3 if specified, the response including in3-section is returned\n\ --debug -debug if given incubed will output debug information when executing\n\ --quiet -q quiet\n\ --human -h human readable, which removes the json -structure and oly displays the values\n\ --test-request -tr runs test request when showing in3_weights\n\ --test-health-request -thr runs test request including health-check when showing in3_weights\n\ --multisig -ms adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...\n\ ---signatures -sigs add additional signatures, which will be useds when sending through a multisig!\n\ ---response-in -ri read response from stdin\n\ ---response-out -ro write raw response to stdout\n\ ---file-in -fi reads a prerecorded request from the filepath and executes it with the recorded data\n\ ---file-out -fo records a request and writes the reproducable data in a file (including all cache-data, timestamps \n\ +--ms.signatures -sigs add additional signatures, which will be useds when sending through a multisig!\n\ +--response.in -ri read response from stdin\n\ +--response.out -ro write raw response to stdout\n\ +--file.in -fi reads a prerecorded request from the filepath and executes it with the recorded data\n\ +--file.out -fo records a request and writes the reproducable data in a file (including all cache-data, timestamps \n\ --nodelist -nl a coma seperated list of urls (or address:url) to be used as fixed nodelist\n\ --bootnodes -bn a coma seperated list of urls (or address:url) to be used as boot nodes\n\ --onlysign -os only sign, don't send the raw Transaction\n\ +--noproof -np alias for --proof=none\n\ --version -v displays the version\n\ --help -h displays this help message\n\ \n\ @@ -121,6 +124,7 @@ const char* aliases[] = { "c", "chainId", "f", "finality", "a", "maxAttempts", + "kin3", "keepIn3=true", "x", "experimental=true", "p", "proof", "l", "replaceLatestBlock", @@ -137,6 +141,7 @@ const char* aliases[] = { "k", "key", "pk", "pk", "ns", "nostats=true", + "ccache", "clearCache=true", "e", "eth=true", "port", "port", "am", "allowed-methods", @@ -146,6 +151,8 @@ const char* aliases[] = { "d", "data", "gp", "gas_price", "gas", "gas", + "nonce", "nonce", + "test", "test", "path", "path", "ns", "sigtype", "pwd", "password", @@ -153,21 +160,21 @@ const char* aliases[] = { "w", "wait=true", "json", "json=true", "hex", "hex=true", - "kin3", "keepin3=true", "debug", "debug=true", "q", "quiet=true", "h", "human=true", "tr", "test-request=true", "thr", "test-health-request=true", "ms", "multisig", - "sigs", "signatures", - "ri", "response-in", - "ro", "response-out", - "fi", "file-in", - "fo", "file-out", + "sigs", "ms.signatures", + "ri", "response.in=true", + "ro", "response.out=true", + "fi", "file.in", + "fo", "file.out", "nl", "nodelist", "bn", "bootnodes", "os", "onlysign=true", + "np", "proof=none", "v", "version=true", "h", "help=true", NULL}; diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml index 6f82ce6e9..c197b2b2d 100644 --- a/c/src/cmd/in3/in3.yml +++ b/c/src/cmd/in3/in3.yml @@ -4,6 +4,11 @@ config: cmd: ns type: bool example: true + clearCache : + descr: clears the cache before performing any operation. + cmd: ccache + type: bool + example: true eth : cmd: e type: bool @@ -49,13 +54,23 @@ config: type: uint descr: 'the gas limit to use when sending transactions. (default: 100000)' example: 100000 + nonce : + cmd: nonce + type: uint + descr: 'the nonce. (default: will be fetched useing eth_getTransactionCount)' + example: 2 + test : + cmd: test + type: string + descr: creates a new json-test written to stdout with the name as specified. + example: test_blockNumber path : cmd: path type: string descr: 'the HD wallet derivation path . We can pass in simplified way as hex string i.e [44,60,00,00,00] => 0x2c3c000000' example: '0x2c3c000000' sigtype: - cmd: ns + cmd: st type: string enum: raw: hash the raw data @@ -89,11 +104,6 @@ config: type: bool descr: if given the result will be returned as hex. example: true - keepin3 : - cmd: kin3 - type: bool - descr: if specified, the response including in3-section is returned - example: true debug : cmd: debug type: bool @@ -124,27 +134,27 @@ config: type: address descr: adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig(s) ) example: '0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6' - signatures : + ms.signatures : cmd: sigs type: bytes descr: add additional signatures, which will be useds when sending through a multisig! example: 0x7d1c10184fa178ebb5b10a9aa6230a255c5c59f6ab00f111c32258f3a53bd1dead143dd5d7eae3737c7b0f21843afcdd27a1b8f0 - response-in: + response.in: cmd: ri - type: string + type: bool descr: read response from stdin - example: response.json - response-out: + example: true + response.out: cmd: ro - type: string + type: bool descr: write raw response to stdout - example: response.json - file-in: + example: true + file.in: cmd: fi type: string descr: reads a prerecorded request from the filepath and executes it with the recorded data. (great for debugging) example: record.txt - file-out: + file.out: cmd: fo type: string descr: records a request and writes the reproducable data in a file (including all cache-data, timestamps ...) @@ -164,12 +174,24 @@ config: type: bool descr: only sign, don't send the raw Transaction example: true + noproof: + alias: proof=none + cmd: np + type: bool + descr: alias for --proof=none + example: true + nostats: + alias: stats=false + cmd: ns + type: bool + descr: alias for --stats=false, which will mark all requests as not counting in the stats + example: true version: cmd: v type: bool descr: displays the version example: true - help: + help: cmd: h type: bool descr: displays this help message diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index acc82272c..d408c78de 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -52,7 +52,16 @@ in3: example: true optional: true default: false + cmd: kin3 + stats: + type: bool + descr: if true, requests sent will be used for stats. + example: false + optional: true + default: true + + useBinary: type: bool descr: if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 04741d914..f9325867d 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -100,6 +100,7 @@ args=( '--maxAttempts=[max number of attempts in case a response is rejected]:maxAttempts:()' '-a[max number of attempts in case a response is rejected]:maxAttempts:()' '--keepIn3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' +'-kin3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' '--useBinary[if true the client will use binary format]' '--experimental[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' '-x[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' @@ -154,6 +155,8 @@ args=( '--btc.maxDiff=[max increase (in percent) of the difference between targets when accepting new targets]:maxDiff:()' '--nostats[no stats if set requests will not be part of the official metrics and considered a service request]' '-ns[no stats if set requests will not be part of the official metrics and considered a service request]' +'--clearCache[clears the cache before performing any operation]' +'-ccache[clears the cache before performing any operation]' '--eth[converts the result (as wei) to ether]' '-e[converts the result (as wei) to ether]' '--port=[if specified it will run as http-server listening to the given port]:port:()' @@ -172,6 +175,10 @@ args=( '-gp[the gas price to use when sending transactions]:gas_price:()' '--gas=[the gas limit to use when sending transactions]:gas:()' '-gas[the gas limit to use when sending transactions]:gas:()' +'--nonce=[the nonce]:nonce:()' +'-nonce[the nonce]:nonce:()' +'--test=[creates a new json-test written to stdout with the name as specified]:test:()' +'-test[creates a new json-test written to stdout with the name as specified]:test:()' '--path=[the HD wallet derivation path ]:path:()' '-path[the HD wallet derivation path ]:path:()' '--sigtype=[the type of the signature data]:sigtype:(raw hash eth_sign)' @@ -186,8 +193,6 @@ args=( '-json[if given the result will be returned as json, which is especially important for eth_call results wit...]' '--hex[if given the result will be returned as hex]' '-hex[if given the result will be returned as hex]' -'--keepin3[if specified, the response including in3-section is returned]' -'-kin3[if specified, the response including in3-section is returned]' '--debug[if given incubed will output debug information when executing]' '-debug[if given incubed will output debug information when executing]' '--quiet[quiet]' @@ -200,22 +205,24 @@ args=( '-thr[runs test request including health-check when showing in3_weights]' '--multisig=[adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...]:multisig:()' '-ms[adds a multisig as signer this needs to be done in the right order! (first the pk then the multisaig...]:multisig:()' -'--signatures=[add additional signatures, which will be useds when sending through a multisig!]:signatures:()' -'-sigs[add additional signatures, which will be useds when sending through a multisig!]:signatures:()' -'--response-in=[read response from stdin]:response-in:()' -'-ri[read response from stdin]:response-in:()' -'--response-out=[write raw response to stdout]:response-out:()' -'-ro[write raw response to stdout]:response-out:()' -'--file-in=[reads a prerecorded request from the filepath and executes it with the recorded data]:file-in:()' -'-fi[reads a prerecorded request from the filepath and executes it with the recorded data]:file-in:()' -'--file-out=[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file-out:()' -'-fo[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file-out:()' +'--ms.signatures=[add additional signatures, which will be useds when sending through a multisig!]:ms.signatures:()' +'-sigs[add additional signatures, which will be useds when sending through a multisig!]:ms.signatures:()' +'--response.in[read response from stdin]' +'-ri[read response from stdin]' +'--response.out[write raw response to stdout]' +'-ro[write raw response to stdout]' +'--file.in=[reads a prerecorded request from the filepath and executes it with the recorded data]:file.in:()' +'-fi[reads a prerecorded request from the filepath and executes it with the recorded data]:file.in:()' +'--file.out=[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file.out:()' +'-fo[records a request and writes the reproducable data in a file (including all cache-data, timestamps ]:file.out:()' '--nodelist=[a coma seperated list of urls (or address:url) to be used as fixed nodelist]:nodelist:()' '-nl[a coma seperated list of urls (or address:url) to be used as fixed nodelist]:nodelist:()' '--bootnodes=[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' '-bn[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' '--onlysign[only sign, don't send the raw Transaction]' '-os[only sign, don't send the raw Transaction]' +'--noproof[alias for --proof=none]' +'-np[alias for --proof=none]' '--version[displays the version]' '-v[displays the version]' '--help[displays this help message]' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 64f297b45..c23be640f 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -82,7 +82,7 @@ function handle_config(conf, pre, title, descr) { } } - asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + pre + key + (c.type == 'bool' ? '=true' : '') + '",')); + asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + (c.alias || (pre + key + (c.type == 'bool' ? '=true' : ''))) + '",')); main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(7) + short_descr(c.descr)) let s = '' if (c.descr) s += '[' + short_descr(c.descr) + ']' From 5186bc45af45c7aeef39e014e27633fc7ae54a33 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:02:16 +0200 Subject: [PATCH 044/221] format --- c/src/cmd/in3/main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 2df9bc024..4ed159749 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -90,10 +90,7 @@ // helpstring void show_help(char* name) { - recorder_print(0, "Usage: %s method ... \n\ -\n\ -%s", - name, help_args); + recorder_print(0, "Usage: %s method ... \n\n%s", name, help_args); } _Noreturn static void die(char* msg) { recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); From e153958eb9af0b4b3f5773ec171dca23823543f8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:02:41 +0200 Subject: [PATCH 045/221] format again --- c/src/cmd/in3/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 4ed159749..3a4b5db58 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -90,7 +90,7 @@ // helpstring void show_help(char* name) { - recorder_print(0, "Usage: %s method ... \n\n%s", name, help_args); + recorder_print(0, "Usage: %s method ... \n\n%s", name, help_args); } _Noreturn static void die(char* msg) { recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); From d1fd3ca5a713da418c923206a3d37f5ccece8284 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:03:01 +0200 Subject: [PATCH 046/221] support url as array --- c/src/pay/zksync/zksync.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index 1e1edf9a1..195f73b4a 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -288,10 +288,16 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { } _free(conf->musig_urls); } - conf->musig_urls = _calloc(d_len(urls), sizeof(char*)); - for (int i = 0; i < d_len(urls); i++) { - char* s = d_get_string_at(urls, i); - if (s) conf->musig_urls[i] = _strdupn(s, -1); + if (d_type(urls) == T_STRING) { + conf->musig_urls = _calloc(2, sizeof(char*)); + conf->musig_urls[1] = _strdupn(d_string(urls), -1); + } + else if (d_type(urls) == T_ARRAY) { + conf->musig_urls = _calloc(d_len(urls), sizeof(char*)); + for (int i = 0; i < d_len(urls); i++) { + char* s = d_get_string_at(urls, i); + if (s) conf->musig_urls[i] = _strdupn(s, -1); + } } } d_token_t* create2 = d_get(ctx->token, CONFIG_KEY("create2")); From cbef1c0b8cf361388111bb5aedf9a2c94e8ecdbc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:06:16 +0200 Subject: [PATCH 047/221] add refactpred files --- c/src/cmd/in3/handlers.h | 6 + c/src/cmd/in3/helper.c | 321 +++++++++++++++++++++++++++++++++ c/src/cmd/in3/helper.h | 48 +++++ c/src/cmd/in3/main2.c | 51 ++++++ c/src/cmd/in3/option_handler.c | 252 ++++++++++++++++++++++++++ c/src/cmd/in3/req_exec.c | 87 +++++++++ c/src/cmd/in3/req_exec.h | 9 + c/src/cmd/in3/rpc_handler.c | 0 c/src/cmd/in3/transport.c | 116 ++++++++++++ c/src/cmd/in3/transport.h | 9 + c/src/cmd/in3/tx.c | 79 ++++++++ c/src/cmd/in3/tx.h | 18 ++ c/src/cmd/in3/weights.c | 7 + c/src/cmd/in3/weights.h | 8 + 14 files changed, 1011 insertions(+) create mode 100644 c/src/cmd/in3/handlers.h create mode 100644 c/src/cmd/in3/helper.c create mode 100644 c/src/cmd/in3/helper.h create mode 100644 c/src/cmd/in3/main2.c create mode 100644 c/src/cmd/in3/option_handler.c create mode 100644 c/src/cmd/in3/req_exec.c create mode 100644 c/src/cmd/in3/req_exec.h create mode 100644 c/src/cmd/in3/rpc_handler.c create mode 100644 c/src/cmd/in3/transport.c create mode 100644 c/src/cmd/in3/transport.h create mode 100644 c/src/cmd/in3/tx.c create mode 100644 c/src/cmd/in3/tx.h create mode 100644 c/src/cmd/in3/weights.c create mode 100644 c/src/cmd/in3/weights.h diff --git a/c/src/cmd/in3/handlers.h b/c/src/cmd/in3/handlers.h new file mode 100644 index 000000000..719f85dc6 --- /dev/null +++ b/c/src/cmd/in3/handlers.h @@ -0,0 +1,6 @@ +#include "../../core/client/plugin.h" + +bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char** argv); + +void init_env(in3_t* c, int argc, char* argv[]); +void init_recorder(int* argc, char*** argv); \ No newline at end of file diff --git a/c/src/cmd/in3/helper.c b/c/src/cmd/in3/helper.c new file mode 100644 index 000000000..2eeb50330 --- /dev/null +++ b/c/src/cmd/in3/helper.c @@ -0,0 +1,321 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +/** @file + * simple commandline-util sending in3-requests. + * */ +#include "helper.h" +#include "handlers.h" + +#ifndef IN3_VERSION +#define IN3_VERSION "local" +#endif + +_Noreturn void die(char* msg) { + recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); + recorder_exit(EXIT_FAILURE); +} +void print_hex(uint8_t* data, int len) { + recorder_print(0, "0x"); + for (int i = 0; i < len; i++) recorder_print(0, "%02x", data[i]); + recorder_print(0, "\n"); +} + +// helper to read the password from tty +void read_pass(char* pw, int pwsize) { + int i = 0, ch = 0; + recorder_print(1, COLORT_HIDDEN); //conceal typing and save position + while (true) { + ch = getchar(); + if (ch == '\r' || ch == '\n' || ch == EOF) break; //get characters until CR or NL + if (i < pwsize - 1) { //do not save pw longer than space in pw + pw[i] = ch; //longer pw can be entered but excess is ignored + pw[i + 1] = 0; + } + i++; + } + recorder_print(1, COLORT_RESETHIDDEN); //reveal typing +} + +void configure_opt(in3_t* c, char* name, char* value, int argc, char** argv) { + sb_t sb = {0}; + + // handle options + if (handle_option(c, name, value, &sb, argc, argv)) return; + if (sb.data) { + char* p = strtok(name, "."); + sb_add_char(&sb, '{'); + int b = 1; + while (p) { + char* next = strtok(NULL, "."); + if (!next) { + if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) + sb_print(&sb, "\"%s\":%s", p, value); + else + sb_print(&sb, "\"%s\":\"%s\"", p, value); + break; + } + b++; + sb_print(&sb, "\"%s\":{", p); + p = next; + continue; + } + for (; b; b--) sb_add_char(&sb, '}'); + } + char* error = in3_configure(c, sb.data); + _free(sb.data); + if (error) { + char* msg = _malloc(200 + (strlen(error) + strlen(name) + strlen(value))); + sprintf(msg, "Invalid option '--%s=%s' : %s", name, value, error); + die(msg); + } +} +void configure(in3_t* c, char* name, char* value) { + configure_opt(c, name, value, 0, NULL); +} +bool configure_arg(in3_t* c, char** args, int* index, int argc) { + if (arg[0] != '-') return false; + const char* arg = args[*index]; + char* value = strchr(arg, '='); + char* name = NULL; + if (arg[1] && arg[1] != '-') { + for (int i = 0; aliases[i]; i += 2) { + if (strcmp(aliases[i], arg + 1) == 0) { + name = alloca(strlen(aliases[i + 1] + 3)); + name[0] = (name[1] = '-'); + strcpy(name + 2, aliases[i + 1]); + value = strchr(name, '='); + if (!value) { + if (argc - 1 <= *index) die("missing value for option"); + *index += 1; + value = args[*index]; + } + else + *value = 0; + break; + } + } + if (!name) die("unknown option!"); + } + + if (!value) { + value = "true"; + name = alloca(strlen(arg) + 1); + strcpy(name, arg); + } + else { + value++; + if (!name) { + name = alloca(value - arg); + strncpy(name, arg, value - arg - 1); + name[value - arg - 1] = 0; + } + } + + if (name[0] == '-' && name[1] == '-') name += 2; + if (!value) return false; + configure_opt(c, name, value, argc, args); + return true; +} + +// accepts a value as +// 0.1eth +// 2keth +// 2.3meth +char* get_wei(char* val) { + if (*val == '0' && val[1] == 'x') return val; + bytes32_t tmp; + int s = string_val_to_bytes(val, NULL, tmp); + if (s < 0) die("Invalid numeric value"); + char* res = _malloc(s * 2 + 3); + bytes_to_hex(tmp, s, res + 2); + if (res[2] == '0') res++; + res[0] = '0'; + res[1] = 'x'; + return res; +} + +char* resolve(in3_t* c, char* name) { + if (!name) return NULL; + if (name[0] == '0' && name[1] == 'x') return name; + if (strstr(name, ".eth")) { + char* params = alloca(strlen(name) + 10); + sprintf(params, "[\"%s\"]", name); + char *res = NULL, *err = NULL; + in3_client_rpc(c, "in3_ens", params, &res, &err); + if (err) { + res = alloca(strlen(err) + 100); + sprintf(res, "Could not resolve %s : %s", name, err); + die(res); + } + if (res[0] == '"') { + res[strlen(res) - 1] = 0; + res++; + } + return res; + } + return name; +} + +// read data from a file and return the bytes +bytes_t readFile(FILE* f) { + if (!f) die("Could not read the input file"); + size_t allocated = 1024, len = 0, r; + uint8_t* buffer = _malloc(1025); + while (1) { + r = fread(buffer + len, 1, allocated - len, f); + len += r; + if (feof(f)) break; + size_t new_alloc = allocated * 2 + 1; + buffer = _realloc(buffer, new_alloc, allocated); + allocated = new_alloc; + } + buffer[len] = 0; + return bytes(buffer, len); +} + +// read from stdin and try to optimize hexdata. +bytes_t* get_std_in() { + if (feof(stdin)) return NULL; + bytes_t content = readFile(stdin); + + // this check tries to discover a solidity compilation poutput + char* bin = strstr((char*) content.data, "\nBinary: \n"); + if (bin) { + bin += 10; + char* end = strstr(bin, "\n"); + if (end) + return hex_to_new_bytes(bin, end - bin); + } + + // is it content starting with 0x, we treat it as hex otherwisae as rwa string + bytes_t* res = (content.len > 1 && *content.data == '0' && content.data[1] == 'x') + ? hex_to_new_bytes((char*) content.data + 2, content.len - 2) + : hex_to_new_bytes((char*) content.data, content.len); + _free(content.data); + return res; +} + +void print_val(d_token_t* t) { + switch (d_type(t)) { + case T_ARRAY: + case T_OBJECT: { + char* level = d_get_string(t, key("level")); + if (level) { + char* msg = d_get_string(t, key("msg")); + if (strcmp(level, "main") == 0) recorder_print(0, COLOR_GREEN_STR "\n", msg); + if (strcmp(level, "info") == 0) recorder_print(0, "%s\n", msg); + if (strcmp(level, "warning") == 0) recorder_print(0, COLOR_YELLOW_STR "\n", msg); + if (strcmp(level, "error") == 0) recorder_print(0, COLOR_RED_STR "\n", msg); + } + else { + for (d_iterator_t it = d_iter(t); it.left; d_iter_next(&it)) + print_val(it.token); + } + } break; + case T_BOOLEAN: + recorder_print(0, "%s\n", d_int(t) ? "true" : "false"); + break; + case T_INTEGER: + recorder_print(0, "%i\n", d_int(t)); + break; + case T_BYTES: + if (t->len < 9) + recorder_print(0, "%" PRId64 "\n", d_long(t)); + else { + recorder_print(0, "0x"); + for (int i = 0; i < (int) t->len; i++) recorder_print(0, "%02x", t->data[i]); + recorder_print(0, "\n"); + } + break; + case T_NULL: + recorder_print(0, "NULL\n"); + break; + case T_STRING: + recorder_print(0, "%s\n", d_string(t)); + break; + } +} +// decode pk +void read_pk(char* pk_file, char* pwd, in3_t* c, char* method) { + if (pk_file) { + if (!pwd) { + recorder_print(1, "Passphrase:\n"); + pwd = malloc(500); + read_pass(pwd, 500); + } + char* content; + if (strcmp(pk_file, "-") == 0) + content = (char*) readFile(stdin).data; + else if (pk_file[0] == '{') + content = pk_file; + else + content = (char*) readFile(fopen(pk_file, "r")).data; + + json_ctx_t* key_json = parse_json(content); + if (!key_json) die("invalid json in pk file"); + + uint8_t* pk_seed = malloc(32); + if (decrypt_key(key_json->result, pwd, pk_seed)) die("Invalid key"); + + if (!method || strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0) { + char tmp[64]; + bytes_to_hex(pk_seed, 32, tmp); + recorder_print(0, "0x%s\n", tmp); + recorder_exit(0); + } + else + eth_set_pk_signer(c, pk_seed); + } +} + +char* get_argument(int argc, char* argv[], char* alias, char* arg, bool has_value) { + int l = strlen(arg); + for (int i = 1; i < argc; i++) { + if (alias && strcmp(alias, argv[i]) == 0) + return has_value ? (i + 1 < argc ? argv[i + 1] : NULL) : argv[i]; + if (strncmp(arg, argv[i], l)) { + if (argv[i][l] == 0) + return has_value ? (i + 1 < argc ? argv[i + 1] : NULL) : argv[i]; + else if (argv[i][l] == '=') + return argv[i] + l + 1; + } + } + return NULL; +} + +uint32_t* get_output_conf() { + static uint32_t conf = 0; + return &conf; +} \ No newline at end of file diff --git a/c/src/cmd/in3/helper.h b/c/src/cmd/in3/helper.h new file mode 100644 index 000000000..4004c4e69 --- /dev/null +++ b/c/src/cmd/in3/helper.h @@ -0,0 +1,48 @@ +#include "../../core/client/keys.h" +#include "../../core/client/plugin.h" +#include "../../core/client/version.h" +#include "../../core/util/bitset.h" +#include "../../core/util/colors.h" +#include "../../core/util/data.h" +#include "../../core/util/debug.h" +#include "../../core/util/log.h" +#include "../../core/util/mem.h" +#include +#include +#include +#include +#include +#include + +_Noreturn void die(char* msg); + +void print_hex(uint8_t* data, int len); + +void read_pass(char* pw, int pwsize); + +void configure(in3_t* c, char* name, char* value); +bool configure_arg(in3_t* c, char** args, int* index, int argc); + +char* get_wei(char* val); + +char* resolve(in3_t* c, char* name); + +bytes_t readFile(FILE* f); + +bytes_t* get_std_in(); + +void read_pk(char* pk_file, char* pwd, in3_t* c, char* method); + +void print_val(d_token_t* t); + +char* get_argument(int argc, char* argv[], char* alias, char* arg, bool has_value); + +uint32_t* get_output_conf(); + +typedef enum output { + out_human = 1, + out_hex = 2, + out_json = 4, + out_eth = 8, + out_debug = 16 +} output_t; diff --git a/c/src/cmd/in3/main2.c b/c/src/cmd/in3/main2.c new file mode 100644 index 000000000..423b4384e --- /dev/null +++ b/c/src/cmd/in3/main2.c @@ -0,0 +1,51 @@ +#include "handlers.h" +#include "helper.h" +#include "req_exec.h" +#include "transport.h" +#include "tx.h" + +int main(int argc, char* argv[]) { + // we want to verify all + in3_log_set_level(LOG_INFO); + + // define vars + char* method = NULL; + sb_t* args = sb_new("["); + in3_t* c = in3_for_chain(CHAIN_ID_MAINNET); + + init_transport(c); + init_recorder(&argc, &argv); + init_env(c, argc, argv); + + // parse arguments + for (int i = 1; i < argc; i++) { + if (configure_arg(c, argv, &i, argc)) continue; + // now handle arguments for special methods + if (method == NULL) + method = argv[i]; + else if (strcmp(method, "sign") == 0 && !get_txdata()->data) + get_txdata()->data = b_new((uint8_t*) argv[i], strlen(argv[i])); + else if (get_txdata()->sig == NULL && (strcmp(method, "call") == 0 || strcmp(method, "send") == 0 || strcmp(method, "abi_encode") == 0 || strcmp(method, "abi_decode") == 0)) + get_txdata()->sig = argv[i]; + else { + // otherwise we add it to the params + if (args->len > 1) sb_add_char(args, ','); + if (*argv[i] >= '0' && *argv[i] <= '9' && *(argv[i] + 1) != 'x' && strcmp(method, "in3_toWei") && c->chain.chain_id != CHAIN_ID_BTC) + sb_print(args, "\"%s\"", get_wei(argv[i])); + else + sb_print(args, + (argv[i][0] == '{' || argv[i][0] == '[' || strcmp(argv[i], "true") == 0 || strcmp(argv[i], "false") == 0 || (*argv[i] >= '0' && *argv[i] <= '9' && strlen(argv[i]) < 16 && *(argv[i] + 1) != 'x')) + ? "%s" + : "\"%s\"", + strcmp(method, "in3_ens") ? resolve(c, argv[i]) : argv[i]); + } + } + sb_add_char(args, ']'); + + if (!method) check_server(c); + + // execute + char *result = NULL, *error = NULL; + + check_last_output(); +} \ No newline at end of file diff --git a/c/src/cmd/in3/option_handler.c b/c/src/cmd/in3/option_handler.c new file mode 100644 index 000000000..fe8e91e8f --- /dev/null +++ b/c/src/cmd/in3/option_handler.c @@ -0,0 +1,252 @@ +#include "args.h" +#include "handlers.h" +#include "helper.h" +#include "req_exec.h" +#include "transport.h" +#include "tx.h" +#include "weights.h" +#define CHECK_OPTION(name, fn) \ + if (strcmp(key, name) == 0) return fn; +#ifndef IN3_VERSION +#define IN3_VERSION "local" +#endif + +static bool set_chainId(char* value, sb_t* conf) { + if (strstr(id, "://") == NULL) return false; + sb_add_chars(conf, "{\"rpc\":\""); + sb_add_escaped_chars(conf, value); + sb_add_chars(conf, "\"}"); + return false; +} + +bool show_help() { + recorder_print(0, "Usage: in3 method ... \n\n%s", name, help_args); + recorder_exit(0); + return true; +} +bool show_version() { + recorder_print(0, "in3 " IN3_VERSION "\nbuild " __DATE__ " with"); +#ifdef TEST + recorder_print(0, " -DTEST=true"); +#endif +#ifdef EVM_GAS + recorder_print(0, " -DEVM_GAS=true"); +#endif +#ifdef CMD + recorder_print(0, " -DCMD=true"); +#endif +#ifdef IN3_MATH_FAST + recorder_print(0, " -DFAST_MATH=true"); +#endif +#ifdef IN3_SERVER + recorder_print(0, " -DIN3_SERVER=true"); +#endif +#ifdef USE_CURL + recorder_print(0, " -DUSE_CURL=true"); +#else + recorder_print(0, " -DUSE_CURL=false"); +#endif + recorder_print(0, "\n(c) " IN3_COPYRIGHT "\n"); + recorder_exit(0); + return true; +} + +#ifdef NODESELECT_DEF +static void set_nodelist(in3_t* c, char* nodes, sb_t* sb, bool update) { + if (!update) c->flags = FLAGS_STATS | FLAGS_BOOT_WEIGHTS | (c->flags & FLAGS_ALLOW_EXPERIMENTAL); + char* cpy = alloca(strlen(nodes) + 1); + in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); + if (!update && nl->nodelist_upd8_params) { + _free(nl->nodelist_upd8_params); + nl->nodelist_upd8_params = NULL; + } + memcpy(cpy, nodes, strlen(nodes) + 1); + char* s = NULL; + sb_add_chars(sb, "{\"nodeRegistry\":{\"needsUpdate\":false,\"nodeList\":["); + for (char* next = strtok(cpy, ","); next; next = strtok(NULL, ",")) { + if (next != cpy) sb_add_char(sb, ','); + str_range_t address, url; + + if (*next == '0' && next[1] == 'x' && (s = strchr(next, ':'))) { + address = (str_range_t){.data = next, .len = s - next}; + url = (str_range_t){.data = s + 1, .len = strlen(s + 1)}; + } + else { + address = (str_range_t){.data = "0x1234567890123456789012345678901234567890", .len = 42}; + url = (str_range_t){.data = next, .len = strlen(next)}; + } + sb_add_chars(sb, "{\"address\":\""); + sb_add_range(sb, address.data, 0, address.len); + sb_add_chars(sb, "\",\"url\":\""); + sb_add_range(sb, url.data, 0, url.len); + sb_add_chars(sb, "\",\"props\":\"0xffff\"}"); + } + sb_add_chars(sb, "]}}}"); + return false; +} +#endif + +static bool set_data(char* value) { + if (strcmp(value, "-") == 0) + get_txdata()->data = get_std_in(); + else if (*value == '0' && value[1] == 'x') + get_txdata()->data = hex_to_new_bytes(value + 2, strlen(value) - 2); + else { + FILE* f = fopen(value, "r"); + bytes_t content = readFile(f); + get_txdata()->data = hex_to_new_bytes((char*) content.data + 2, content.len - 2); + fclose(f); + } + return true; +} +static bool set_string(char** dst, char* value) { + *dst = value; + return true; +} +static bool set_uint64(uint64_t* dst, char* value) { + // TODO support gwei or hex + *dst = (uint64_t) atoll(value); + return true; +} +static bool set_uint32(uint32_t* dst, char* value) { + // TODO support gwei or hex + *dst = (uint32_t) atoi(value); + return true; +} +static bool set_create2(char* value, sb_t* sb) { + if (strlen(value) != 176) die("create2-arguments must have the form -zc2 ::"); + char tmp[177], t2[500]; + memcpy(tmp, c2val, 177); + tmp[42] = tmp[109] = 0; + sprintf(t2, "{\"zksync\":{\"signer_type\":\"create2\",\"create2\":{\"creator\":\"%s\",\"codehash\":\"%s\",\"saltarg\":\"%s\"}}}", tmp, tmp + 43, tmp + 110); + sb_add_chars(sb, t2); + return false; +} +static bool set_recorder(in3_t* c, char* value, sb_t* conf, int argc, char** argv, bool write) { + if (write) + recorder_write_start(c, value, argc, argv); + else + recorder_read_start(c, value); + return true; +} +static bool set_pk(in3_t* c, char* value, sb_t* conf, int argc, char** argv) { + if (value[0] != '0' || value[1] != 'x') { + read_pk(value, get_argument(argc, argv, "-pwd", "--password", true), c, NULL); + return true; + } + else + return false; +} +static bool set_flag(uint32_t* dst, uint32_t val, char* value) { + if (strcmp(value, "true") == 0) + *dst |= val; + else + *dst ^= val; + return true; +} +static bool set_quiet() { + in3_log_set_level(LOG_FATAL); + return true; +} +static bool set_debug() { + in3_log_set_quiet(false); + in3_log_set_level(LOG_TRACE); + *get_output_conf() |= out_debug; + return true; +} + +#ifdef LEDGER_NANO +static bool set_path(in3_t* c, char* value) { + if (value[0] == '0' && value[1] == 'x') { + bytes32_t path; + hex_to_bytes(value, -1, path, 5); + eth_ledger_set_signer_txn(c, path); + return true; + } + else + die("Invalid path for nano ledger"); +} +#endif +#ifdef MULTISIG +static bool set_ms(in3_t* c, char* value) { + address_t adr; + if (hex_to_bytes(value, -1, adr, 20) != 20) die("-ms must be exactly 20 bytes"); + add_gnosis_safe(c, adr); + return true; +} +#endif +bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char** argv) { + CHECK_OPTION("test", set_test_transport(c, value)) + CHECK_OPTION("clearCache", true) + CHECK_OPTION("password", true) + CHECK_OPTION("help", show_help()) + CHECK_OPTION("version", show_version()) + CHECK_OPTION("chainId", set_chainId(value, conf)) + CHECK_OPTION("from", set_string(&get_txdata()->from, value)) + CHECK_OPTION("to", set_string(&get_txdata()->to, value)) + CHECK_OPTION("gas", set_uint64(&get_txdata()->gas, value)) + CHECK_OPTION("gas_price", set_uint64(&get_txdata()->gas_price, value)) + CHECK_OPTION("nonce", set_uint64(&get_txdata()->nonce, value)) + CHECK_OPTION("wait", set_uint32(&get_txdata()->wait, "1")) + CHECK_OPTION("block", set_string(&get_txdata()->block, value)) + CHECK_OPTION("value", set_string(&get_txdata()->value, get_wei(value))) + CHECK_OPTION("zksync.create2", set_create2(value, conf)) + CHECK_OPTION("test-request", set_flag(get_weightsdata(), weight_test_request, value)) + CHECK_OPTION("test-health-request", set_flag(get_weightsdata(), weight_health, value)) + CHECK_OPTION("response.in", set_recorder(c, value, conf, argc, argv, false)) + CHECK_OPTION("response.out", set_recorder(c, value, conf, argc, argv, true)) + CHECK_OPTION("file.in", set_recorder(c, value, conf, argc, argv, false)) + CHECK_OPTION("file.out", set_recorder(c, value, conf, argc, argv, true)) + CHECK_OPTION("ms.signatures", true) + CHECK_OPTION("multisig", set_ms(c, value)) + CHECK_OPTION("human", set_flag(get_output_conf(), out_human, value)) + CHECK_OPTION("eth", set_flag(get_output_conf(), out_eth, value)) + CHECK_OPTION("hex", set_flag(get_output_conf(), out_hex, value)) + CHECK_OPTION("json", set_flag(get_output_conf(), out_json, value)) + CHECK_OPTION("quiet", set_quiet()) + CHECK_OPTION("port", set_uint32(&get_req_exec()->port, value)) + CHECK_OPTION("allowed-methods", set_string(&get_req_exec()->allowed_methods, value)) + CHECK_OPTION("onlysign", set_onlyshow_rawtx()) + CHECK_OPTION("sigtype", set_string((&get_txdata()->signtype,value)) + CHECK_OPTION("debug", set_debug()) +#ifdef NODESELECT_DEF + CHECK_OPTION("nodelist", set_nodelist(value, conf, false)) + CHECK_OPTION("bootnodes", set_nodelist(value, conf, true)) + CHECK_OPTION("pk", set_pk(c, value, conf, argc, argv)) +#endif +#ifdef LEDGER_NANO + CHECK_OPTION("path", set_path(c, valuev)) +#endif + return false; +} + +void init_recorder(int* argc, char*** argv) { + char* file = get_argument(*argc, *argv, "-fi", "--file.in", true); + if (file) + recorder_update_cmd(file, argc, argv); +} + +void init_env(in3_t* c, int argc, char* argv[]) { + // handle clear cache opt before initializing cache + if (get_argument(argc, argv, "-ccache", "--clearCache", false)) + storage_clear(NULL); + // use the storagehandler to cache data in .in3 + in3_register_file_storage(c); + + // PK + if (getenv("IN3_PK") && !get_argument(argc, argv, "-pk", "--pk", true)) { + char* pks = _strdupn(getenv("IN3_PK"), -1); + bytes32_t pk; + for (char* cc = strtok(pks, ","); cc; cc = strtok(NULL, ",")) { + hex_to_bytes(cc, -1, pk, 32); + eth_set_pk_signer(c, pk); + } + } + + // handle chainId + if (getenv("IN3_CHAIN")) configure(c, "chainId", getenv("IN3_CHAIN")); + +#ifdef ZKSYNC + if (getenv("IN3_ZKS")) configure(c, "zksync.provider_url", getenv("IN3_ZKS")); +#endif +} \ No newline at end of file diff --git a/c/src/cmd/in3/req_exec.c b/c/src/cmd/in3/req_exec.c new file mode 100644 index 000000000..cdeb4f370 --- /dev/null +++ b/c/src/cmd/in3/req_exec.c @@ -0,0 +1,87 @@ +#include "req_exec.h" +#include "../http-server/http_server.h" +#include "helper.h" + +req_exec_t* get_req_exec() { + static req_exec_t val = {0}; + return &val; +} + +static void execute(in3_t* c, FILE* f) { + if (feof(f)) die("no data"); + sb_t* sb = sb_new(NULL); + char first = 0, stop = 0; + int level = 0, d = 0; + while (1) { + d = fgetc(f); + if (d == EOF) { + if (first) + die("Invalid json-data from stdin"); + else + recorder_exit(EXIT_SUCCESS); + } + if (first == 0) { + if (d == '{') + stop = '}'; + else if (d == '[') + stop = ']'; + else + continue; + first = d; + } + + sb_add_char(sb, (char) d); + if (d == first) level++; + if (d == stop) level--; + if (level == 0) { + // time to execute + in3_req_t* ctx = req_new(c, sb->data); + if (ctx->error) + recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":{\"code\":%i,\"message\":\"%s\"}\n", 1, ctx->verification_state, ctx->error); + else { + in3_ret_t ret = in3_send_req(ctx); + uint32_t id = d_get_int(ctx->requests[0], K_ID); + if (ctx->error) { + for (char* x = ctx->error; *x; x++) { + if (*x == '\n') *x = ' '; + } + } + + if (ret == IN3_OK) { + if (c->flags & FLAGS_KEEP_IN3) { + str_range_t rr = d_to_json(ctx->responses[0]); + rr.data[rr.len] = 0; + recorder_print(0, "%s\n", rr.data); + } + else { + d_token_t* result = d_get(ctx->responses[0], K_RESULT); + d_token_t* error = d_get(ctx->responses[0], K_ERROR); + char* r = d_create_json(ctx->response_context, result ? result : error); + if (result) + recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"result\":%s}\n", id, r); + else + recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":%s}\n", id, r); + _free(r); + } + } + else + recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":{\"code\":%i,\"message\":\"%s\"}}\n", id, ctx->verification_state, ctx->error == NULL ? "Unknown error" : ctx->error); + } + req_free(ctx); + first = 0; + sb->len = 0; + } + } +} + +void check_server(in3_t* c) { + if (get_req_exec()->port) { +#ifdef IN3_SERVER + // start server + http_run_server(port, c, allowed_methods); + recorder_exit(0); +#else + die("You need to compile in3 with -DIN3_SERVER=true to start the server."); +#endif + } +} \ No newline at end of file diff --git a/c/src/cmd/in3/req_exec.h b/c/src/cmd/in3/req_exec.h new file mode 100644 index 000000000..5e12f2539 --- /dev/null +++ b/c/src/cmd/in3/req_exec.h @@ -0,0 +1,9 @@ +#include "helper.h" + +typedef struct req_exec { + uint32_t port; + char* allowed_methods; +} req_exec_t; + +req_exec_t* get_req_exec(); +void check_server(in3_t* c); \ No newline at end of file diff --git a/c/src/cmd/in3/rpc_handler.c b/c/src/cmd/in3/rpc_handler.c new file mode 100644 index 000000000..e69de29bb diff --git a/c/src/cmd/in3/transport.c b/c/src/cmd/in3/transport.c new file mode 100644 index 000000000..e6ceca58c --- /dev/null +++ b/c/src/cmd/in3/transport.c @@ -0,0 +1,116 @@ +#include "helper.h" +#ifdef USE_CURL +#include "../../transport/curl/in3_curl.h" +#elif USE_WINHTTP +#include "../../transport/winhttp/in3_winhttp.h" +#else +#include "../../transport/http/in3_http.h" +#endif + +static bool out_response = false; +static bytes_t* last_response; +static bytes_t in_response = {.data = NULL, .len = 0}; +static bool only_show_raw_tx = false; +in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx) { + UNUSED_VAR(plugin_data); + + in3_http_request_t* req = plugin_ctx; + if (action == PLGN_ACT_TRANSPORT_SEND) { +#ifndef DEBUG + if (debug_mode) + fprintf(stderr, "send request to %s: \n" COLORT_RYELLOW "%s" COLORT_RESET "\n", req->urls_len ? req->urls[0] : "none", req->payload); +#endif + if (in_response.len) { + for (unsigned int i = 0; i < req->urls_len; i++) { + req->req->raw_response[i].state = IN3_OK; + sb_add_range(&req->req->raw_response[i].data, (char*) in_response.data, 0, in_response.len); + req->req->raw_response[i].state = IN3_OK; + } + return 0; + } + if (only_show_raw_tx && str_find(req->payload, "\"method\":\"eth_sendRawTransaction\"")) { + char* data = str_find(req->payload, "0x"); + *strchr(data, '"') = 0; + recorder_print(0, "%s\n", data); + recorder_exit(EXIT_SUCCESS); + } + } +#ifdef USE_CURL + in3_ret_t r = send_curl(NULL, action, plugin_ctx); +#elif USE_WINHTTP + in3_ret_t r = send_winhttp(NULL, action, plugin_ctx); +#elif TRANSPORTS + in3_ret_t r = send_http(NULL, action, plugin_ctx); +#else + in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; +#endif + if (action != PLGN_ACT_TRANSPORT_CLEAN) { + last_response = b_new((uint8_t*) req->req->raw_response[0].data.data, req->req->raw_response[0].data.len); +#ifndef DEBUG + if (debug_mode) { + if (req->req->raw_response[0].state == IN3_OK) + fprintf(stderr, "success response \n" COLORT_RGREEN "%s" COLORT_RESET "\n", req->req->raw_response[0].data.data); + else + fprintf(stderr, "error response \n" COLORT_RRED "%s" COLORT_RESET "\n", req->req->raw_response[0].data.data); + } +#endif + } + return r; +} +static char* test_name = NULL; +static in3_ret_t test_transport(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx) { + UNUSED_VAR(plugin_data); + in3_http_request_t* req = plugin_ctx; +#ifdef USE_CURL + in3_ret_t r = send_curl(NULL, action, plugin_ctx); +#elif USE_WINHTTP + in3_ret_t r = send_winhttp(NULL, action, plugin_ctx); +#elif TRANSPORTS + in3_ret_t r = send_http(NULL, action, plugin_ctx); +#else + in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; +#endif + if (r == IN3_OK) { + req->payload[strlen(req->payload) - 1] = 0; + recorder_print(0, "[{ \"descr\": \"%s\",\"chainId\": \"0x1\", \"verification\": \"proof\",\"binaryFormat\": false, \"request\": %s, \"response\": %s }]", test_name, req->payload + 1, req->req->raw_response->data.data); + recorder_exit(0); + } + + return r; +} + +void init_transport(in3_t* c) { + in3_plugin_register(c, PLGN_ACT_TRANSPORT, debug_transport, NULL, true); +#ifdef USE_WINHTTP + configure(c, "requestCount", "1"); +#else + configure(c, "requestCount", "2"); +#endif +} + +bool set_test_transport(in3_t* c, char* name) { + test_name = name; + in3_plugin_register(c, PLGN_ACT_TRANSPORT, test_transport, NULL, true); +} + +bool set_onlyshow_rawtx() { + only_show_raw_tx = true; + return true; +} + +bool set_response_file(bool is_ine) { + if (is_in) + in_response = readFile(stdin); + else + out_response = true; +} + +void check_last_output() { + if (out_response && last_response) { + char* r = alloca(last_response->len + 1); + memcpy(r, last_response->data, last_response->len); + r[last_response->len] = 0; + recorder_print(0, "%s\n", r); + recorder_exit(0); + } +} \ No newline at end of file diff --git a/c/src/cmd/in3/transport.h b/c/src/cmd/in3/transport.h new file mode 100644 index 000000000..cd7d5f20b --- /dev/null +++ b/c/src/cmd/in3/transport.h @@ -0,0 +1,9 @@ +#include "../../core/client/plugin.h" + +in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx); + +void init_transport(in3_t* c); +bool set_test_transport(in3_t* c, char* name); +bool set_onlyshow_rawtx(); +bool set_response_file(bool is_in, char* value); +void check_last_output(); \ No newline at end of file diff --git a/c/src/cmd/in3/tx.c b/c/src/cmd/in3/tx.c new file mode 100644 index 000000000..8e2f0ab47 --- /dev/null +++ b/c/src/cmd/in3/tx.c @@ -0,0 +1,79 @@ +#include "tx.h" +#include "helper.h" + +tx_t* get_txdata() { + static tx_t _tx = {0}; + return &_tx; +} + +// prepare a eth_call or eth_sendTransaction +abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data, char* from) { + char* error = NULL; + bytes_t rdata = {0}; + abi_sig_t* req = fn_sig ? abi_sig_create(fn_sig, &error) : NULL; // only if we have a function signature, we will parse it and create a call_request. + if (error) die(error); // parse-error we stop here. + if (req) { // if type is a tuple, it means we have areuments we need to parse. + json_ctx_t* in_data = parse_json(args->data); // the args are passed as a "[]"- json-array string. + rdata = abi_encode(req, in_data->result, &error); //encode data + if (error) die(error); // we then set the data, which appends the arguments to the functionhash. + json_free(in_data); // of course we clean up ;-) + } // + sb_t* params = sb_new("[{"); // now we create the transactionobject as json-argument. + if (to) { // if this is a deployment we must not include the to-property + sb_add_chars(params, "\"to\":\""); + sb_add_chars(params, to); + sb_add_chars(params, "\" "); + } + if (req || data) { // if we have a request context or explicitly data we create the data-property + if (params->len > 2) sb_add_char(params, ','); // add comma if this is not the first argument + sb_add_chars(params, "\"data\":"); // we will have a data-property + if (req && data) { // if we have a both, we need to concat thewm (this is the case when depkloying a contract with constructorarguments) + uint8_t* full = _malloc(rdata.len - 4 + data->len); // in this case we skip the functionsignature. + memcpy(full, data->data, data->len); + memcpy(full + data->len, rdata.data + 4, rdata.len - 4); + bytes_t bb = bytes(full, rdata.len - 4 + data->len); + sb_add_bytes(params, "", &bb, 1, false); + _free(full); + } + else if (req) + sb_add_bytes(params, "", &rdata, 1, false); + else if (data) + sb_add_bytes(params, "", data, 1, false); + } + + if (block_number) { + sb_add_chars(params, "},\""); + sb_add_chars(params, block_number); + sb_add_chars(params, "\"]"); + } + else { + uint8_t gasdata[8]; + bytes_t g_bytes = bytes(gasdata, 8); + + if (value) { + sb_add_chars(params, ", \"value\":\""); + sb_add_chars(params, value); + sb_add_chars(params, "\""); + } + if (from) { + sb_add_chars(params, ", \"from\":\""); + sb_add_chars(params, from); + sb_add_chars(params, "\""); + } + + if (gas_price) { + long_to_bytes(gas_price, gasdata); + b_optimize_len(&g_bytes); + sb_add_bytes(params, ", \"gasPrice\":", &g_bytes, 1, false); + } + long_to_bytes(gas ? gas : 100000, gasdata); + g_bytes = bytes(gasdata, 8); + b_optimize_len(&g_bytes); + sb_add_bytes(params, ", \"gasLimit\":", &g_bytes, 1, false); + sb_add_chars(params, "}]"); + } + args->len = 0; + sb_add_chars(args, params->data); + sb_free(params); + return req; +} diff --git a/c/src/cmd/in3/tx.h b/c/src/cmd/in3/tx.h new file mode 100644 index 000000000..cecb7e933 --- /dev/null +++ b/c/src/cmd/in3/tx.h @@ -0,0 +1,18 @@ +#include "helper.h" + +typedef struct tx { + bytes_t* data; + char* block; + char* from; + char* to; + uint64_t gas; + uint64_t gas_price; + uint64_t nonce; + char* value; + uint32_t wait; + char* signtype; + char* sig; + +} tx_t; + +tx_t* get_txdata(); \ No newline at end of file diff --git a/c/src/cmd/in3/weights.c b/c/src/cmd/in3/weights.c new file mode 100644 index 000000000..117341a21 --- /dev/null +++ b/c/src/cmd/in3/weights.c @@ -0,0 +1,7 @@ +#include "weights.h" +#include "helper.h" + +uint32_t* get_weightsdata() { + static uint32_t weightdata = 0; + return &weightdata; +} \ No newline at end of file diff --git a/c/src/cmd/in3/weights.h b/c/src/cmd/in3/weights.h new file mode 100644 index 000000000..c5ef65d25 --- /dev/null +++ b/c/src/cmd/in3/weights.h @@ -0,0 +1,8 @@ +#include "helper.h" + +typedef enum output { + weight_test_request = 1, + weight_health = 2 +} output_t; + +uint32_t* get_weightsdata(); \ No newline at end of file From ceb76a5366a3641b8b73a85e1aa7528b2ea1f9e3 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:27:38 +0200 Subject: [PATCH 048/221] remove config --- c/src/cmd/in3/config.c | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 c/src/cmd/in3/config.c diff --git a/c/src/cmd/in3/config.c b/c/src/cmd/in3/config.c deleted file mode 100644 index 5cded2511..000000000 --- a/c/src/cmd/in3/config.c +++ /dev/null @@ -1,12 +0,0 @@ - - -const char* help = "options"; -const char** aliases = { - "p", "proof", - "l", "latest", - "zks", "zksync.provider_url", - --key - k - NULL}; - -bool configure() { -} From 7b1c46a49b6ce05b58fad8f7634674acdfc0df8b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:29:12 +0200 Subject: [PATCH 049/221] debug on failure --- c/ci-analyse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/ci-analyse.yml b/c/ci-analyse.yml index 553a71da6..11158c1a2 100644 --- a/c/ci-analyse.yml +++ b/c/ci-analyse.yml @@ -18,7 +18,7 @@ coverage: script: - mkdir cov_build; cd cov_build - cmake -DIN3API=true -DIN3_LIB=false -DUSE_CURL=false -DTEST=true -DZKSYNC=true -DCODE_COVERAGE=true -DUSE_SEGGER_RTT=false -DTRANSPORTS=false -DCMAKE_BUILD_TYPE=Debug .. - - make -j8 && make ptest + - make -j8 && make CTEST_OUTPUT_ON_FAILURE=1 test - ../scripts/lcov_report.sh | xargs llvm-cov report - ../scripts/lcov_report.sh | xargs llvm-cov show -show-line-counts-or-regions -output-dir=ccov/all-merged -format=html - ../scripts/lcov_report.sh | xargs llvm-cov export -format=lcov > ccov/all-merged/lcov.info From f0b3eda13ab45b1285a2036efbab0fad7a1dc03c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 21:53:53 +0200 Subject: [PATCH 050/221] fix experimental --- c/src/cmd/in3/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 3a4b5db58..cd9c2e93b 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -834,6 +834,8 @@ int main(int argc, char* argv[]) { run_test_request = 1; else if (strcmp(argv[i], "-thr") == 0) run_test_request = 2; + else if (strcmp(argv[i], "-x") == 0) + c->flags |= FLAGS_ALLOW_EXPERIMENTAL; else if (strcmp(argv[i], "-fo") == 0) recorder_write_start(c, argv[++i], argc, argv); else if (strcmp(argv[i], "-fi") == 0) From 48152206e3af06bbd496fbc794964b8cf35b0380 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 23:20:14 +0200 Subject: [PATCH 051/221] fix main again --- c/src/cmd/in3/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index cd9c2e93b..b4e3079db 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -152,7 +152,7 @@ static bool configure_arg(in3_t* c, char** args, int* index, int argc) { if (arg[1] && arg[1] != '-') { for (int i = 0; aliases[i]; i += 2) { if (strcmp(aliases[i], arg + 1) == 0) { - name = alloca(strlen(aliases[i + 1] + 3)); + name = alloca(strlen(aliases[i + 1]) + 3); name[0] = (name[1] = '-'); strcpy(name + 2, aliases[i + 1]); value = strchr(name, '='); @@ -205,6 +205,9 @@ static bool configure_arg(in3_t* c, char** args, int* index, int argc) { continue; } for (; b; b--) sb_add_char(&sb, '}'); + + // printf("_configure\n"); + // in3_log_info("configure %s\n", sb.data); char* error = in3_configure(c, sb.data); if (error) die(error); @@ -834,8 +837,8 @@ int main(int argc, char* argv[]) { run_test_request = 1; else if (strcmp(argv[i], "-thr") == 0) run_test_request = 2; - else if (strcmp(argv[i], "-x") == 0) - c->flags |= FLAGS_ALLOW_EXPERIMENTAL; + // else if (strcmp(argv[i], "-x") == 0) + // c->flags |= FLAGS_ALLOW_EXPERIMENTAL; else if (strcmp(argv[i], "-fo") == 0) recorder_write_start(c, argv[++i], argc, argv); else if (strcmp(argv[i], "-fi") == 0) From 0342955d9fbd77b30cf19557db85c424cb16a875 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 30 Mar 2021 23:28:40 +0200 Subject: [PATCH 052/221] fix memeory issue --- c/src/cmd/in3/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/helper.c b/c/src/cmd/in3/helper.c index 2eeb50330..4576f3fc8 100644 --- a/c/src/cmd/in3/helper.c +++ b/c/src/cmd/in3/helper.c @@ -112,7 +112,7 @@ bool configure_arg(in3_t* c, char** args, int* index, int argc) { if (arg[1] && arg[1] != '-') { for (int i = 0; aliases[i]; i += 2) { if (strcmp(aliases[i], arg + 1) == 0) { - name = alloca(strlen(aliases[i + 1] + 3)); + name = alloca(strlen(aliases[i + 1]) + 3); name[0] = (name[1] = '-'); strcpy(name + 2, aliases[i + 1]); value = strchr(name, '='); From e4cc30657d979a6e1e438e889624243ba6929a12 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 10:25:17 +0200 Subject: [PATCH 053/221] fix nostats --- c/src/cmd/in3/in3.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml index c197b2b2d..62ae610bf 100644 --- a/c/src/cmd/in3/in3.yml +++ b/c/src/cmd/in3/in3.yml @@ -1,9 +1,4 @@ config: - nostats : - descr: no stats if set requests will not be part of the official metrics and considered a service request - cmd: ns - type: bool - example: true clearCache : descr: clears the cache before performing any operation. cmd: ccache From 8670cac91002c37334ab783691ec0027b54465c6 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 10:25:36 +0200 Subject: [PATCH 054/221] update nostats --- c/src/cmd/in3/args.h | 9 +++++---- scripts/_in3.sh | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 3c17350e8..aa103ab03 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -4,6 +4,7 @@ const char* help_args = "\ --includeCode if true, the request should include the codes of all accounts\n\ --maxAttempts -a max number of attempts in case a response is rejected\n\ --keepIn3 -kin3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ +--stats if true, requests sent will be used for stats\n\ --useBinary if true the client will use binary format\n\ --experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ --timeout specifies the number of milliseconds before the request times out\n\ @@ -48,7 +49,6 @@ const char* help_args = "\ --btc configure the Bitcoin verification\n\ --btc.maxDAP max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets\n\ --btc.maxDiff max increase (in percent) of the difference between targets when accepting new targets\n\ ---nostats -ns no stats if set requests will not be part of the official metrics and considered a service request\n\ --clearCache -ccacheclears the cache before performing any operation\n\ --eth -e converts the result (as wei) to ether\n\ --port -port if specified it will run as http-server listening to the given port\n\ @@ -62,7 +62,7 @@ const char* help_args = "\ --nonce -nonce the nonce\n\ --test -test creates a new json-test written to stdout with the name as specified\n\ --path -path the HD wallet derivation path \n\ ---sigtype -ns the type of the signature data\n\ +--sigtype -st the type of the signature data\n\ --password -pwd password to unlock the key\n\ --value -value the value to send when sending a transaction\n\ --wait -w if given, instead returning the transaction, it will wait until the transaction is mined and return ...\n\ @@ -83,6 +83,7 @@ const char* help_args = "\ --bootnodes -bn a coma seperated list of urls (or address:url) to be used as boot nodes\n\ --onlysign -os only sign, don't send the raw Transaction\n\ --noproof -np alias for --proof=none\n\ +--nostats -ns alias for --stats=false, which will mark all requests as not counting in the stats\n\ --version -v displays the version\n\ --help -h displays this help message\n\ \n\ @@ -140,7 +141,6 @@ const char* aliases[] = { "zc2", "zksync.create2", "k", "key", "pk", "pk", - "ns", "nostats=true", "ccache", "clearCache=true", "e", "eth=true", "port", "port", @@ -154,7 +154,7 @@ const char* aliases[] = { "nonce", "nonce", "test", "test", "path", "path", - "ns", "sigtype", + "st", "sigtype", "pwd", "password", "value", "value", "w", "wait=true", @@ -175,6 +175,7 @@ const char* aliases[] = { "bn", "bootnodes", "os", "onlysign=true", "np", "proof=none", + "ns", "stats=false", "v", "version=true", "h", "help=true", NULL}; diff --git a/scripts/_in3.sh b/scripts/_in3.sh index f9325867d..577a54cbf 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -101,6 +101,7 @@ args=( '-a[max number of attempts in case a response is rejected]:maxAttempts:()' '--keepIn3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' '-kin3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' +'--stats[if true, requests sent will be used for stats]' '--useBinary[if true the client will use binary format]' '--experimental[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' '-x[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' @@ -153,8 +154,6 @@ args=( '-pk[registers raw private keys as signers for transactions]:pk:()' '--btc.maxDAP=[max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets]:maxDAP:()' '--btc.maxDiff=[max increase (in percent) of the difference between targets when accepting new targets]:maxDiff:()' -'--nostats[no stats if set requests will not be part of the official metrics and considered a service request]' -'-ns[no stats if set requests will not be part of the official metrics and considered a service request]' '--clearCache[clears the cache before performing any operation]' '-ccache[clears the cache before performing any operation]' '--eth[converts the result (as wei) to ether]' @@ -182,7 +181,7 @@ args=( '--path=[the HD wallet derivation path ]:path:()' '-path[the HD wallet derivation path ]:path:()' '--sigtype=[the type of the signature data]:sigtype:(raw hash eth_sign)' -'-ns[the type of the signature data]:sigtype:(raw hash eth_sign)' +'-st[the type of the signature data]:sigtype:(raw hash eth_sign)' '--password=[password to unlock the key]:password:()' '-pwd[password to unlock the key]:password:()' '--value=[the value to send when sending a transaction]:value:()' @@ -223,6 +222,8 @@ args=( '-os[only sign, don't send the raw Transaction]' '--noproof[alias for --proof=none]' '-np[alias for --proof=none]' +'--nostats[alias for --stats=false, which will mark all requests as not counting in the stats]' +'-ns[alias for --stats=false, which will mark all requests as not counting in the stats]' '--version[displays the version]' '-v[displays the version]' '--help[displays this help message]' From f6eef17ce97922b5a367c1f740aee7d25ee56fd7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 10:43:18 +0200 Subject: [PATCH 055/221] fix handling of send without transport --- c/src/core/client/execute.c | 63 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c index 050afaf08..a247b76ff 100644 --- a/c/src/core/client/execute.c +++ b/c/src/core/client/execute.c @@ -740,45 +740,46 @@ void in3_handle_rpc(in3_req_t* ctx, ctx_req_transports_t* transports) { for (unsigned int i = 0; i < request->urls_len; i++) in3_log_trace("... request to " COLOR_YELLOW_STR "\n... " COLOR_MAGENTA_STR "\n", request->urls[i], i == 0 ? request->payload : ""); - // handle it - in3_plugin_execute_first(ctx, PLGN_ACT_TRANSPORT_SEND, request); - - // debug output - node_match_t* node = request->req->nodes; - for (unsigned int i = 0; i < request->urls_len; i++, node = node ? node->next : NULL) { - if (request->req->raw_response[i].state != IN3_WAITING) { - char* data = request->req->raw_response[i].data.data; + // handle it (only if there is a transport) + if (in3_plugin_execute_first(ctx, PLGN_ACT_TRANSPORT_SEND, request) == IN3_OK) { + + // debug output + node_match_t* node = request->req->nodes; + for (unsigned int i = 0; i < request->urls_len; i++, node = node ? node->next : NULL) { + if (request->req->raw_response[i].state != IN3_WAITING) { + char* data = request->req->raw_response[i].data.data; #ifdef DEBUG - data = format_json(data); + data = format_json(data); #endif - in3_log_trace(request->req->raw_response[i].state - ? "... response(%s): \n... " COLOR_RED_STR "\n" - : "... response(%s): \n... " COLOR_GREEN_STR "\n", - node ? node->url : "intern", data); + in3_log_trace(request->req->raw_response[i].state + ? "... response(%s): \n... " COLOR_RED_STR "\n" + : "... response(%s): \n... " COLOR_GREEN_STR "\n", + node ? node->url : "intern", data); #ifdef DEBUG - _free(data); + _free(data); #endif + } } - } - // in case we have a cptr, we need to save it in the transports - if (request && request->cptr) { - // find a free spot - int index = -1; - for (int i = 0; i < transports->len; i++) { - if (!transports->req[i].req) { - index = i; - break; + // in case we have a cptr, we need to save it in the transports + if (request && request->cptr) { + // find a free spot + int index = -1; + for (int i = 0; i < transports->len; i++) { + if (!transports->req[i].req) { + index = i; + break; + } + } + if (index == -1) { + transports->req = transports->len ? _realloc(transports->req, sizeof(ctx_req_t) * (transports->len + 1), sizeof(ctx_req_t) * transports->len) : _malloc(sizeof(ctx_req_t)); + index = transports->len++; } - } - if (index == -1) { - transports->req = transports->len ? _realloc(transports->req, sizeof(ctx_req_t) * (transports->len + 1), sizeof(ctx_req_t) * transports->len) : _malloc(sizeof(ctx_req_t)); - index = transports->len++; - } - // store the pointers - transports->req[index].req = request->req; - transports->req[index].ptr = request->cptr; + // store the pointers + transports->req[index].req = request->req; + transports->req[index].ptr = request->cptr; + } } // we will cleanup even though the reponses may still be pending From 34c6586c949d6d9439a2705eb1cbec07b753600f Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 21:55:52 +0200 Subject: [PATCH 056/221] added createkey and first working main-impl --- c/src/api/eth1/rpc.yml | 16 +++- c/src/api/eth1/rpc_api.c | 36 ++++++++ c/src/cmd/in3/CMakeLists.txt | 13 ++- c/src/cmd/in3/args.h | 8 ++ c/src/cmd/in3/handlers.h | 2 +- c/src/cmd/in3/helper.c | 140 ++++++++++++++++++++++++------- c/src/cmd/in3/helper.h | 20 ++++- c/src/cmd/in3/in3.yml | 3 + c/src/cmd/in3/main.c | 9 +- c/src/cmd/in3/main2.c | 46 +++++++++- c/src/cmd/in3/option_handler.c | 39 +++++---- c/src/cmd/in3/req_exec.c | 9 +- c/src/cmd/in3/req_exec.h | 4 +- c/src/cmd/in3/rpc_handler.c | 129 ++++++++++++++++++++++++++++ c/src/cmd/in3/transport.c | 14 +++- c/src/cmd/in3/transport.h | 3 +- c/src/cmd/in3/tx.c | 8 +- c/src/cmd/in3/tx.h | 28 ++++--- c/src/cmd/in3/weights.c | 144 +++++++++++++++++++++++++++++++- c/src/cmd/in3/weights.h | 7 +- c/src/tools/recorder/recorder.c | 2 +- scripts/_in3.sh | 1 + scripts/build_rpc_docu.js | 4 +- 23 files changed, 595 insertions(+), 90 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 152bbd13c..7a4acbdc4 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -390,7 +390,21 @@ eth: returns: descr: the Version number - + in3_createKey: + descr: | + Generates 32 random bytes. + If /dev/urandom is available it will be used and should generate a secure random number. + If not the number should not be considered sceure or used in production. + params: + seed: + optional: true + descr: the seed. If given the result will be deterministic. + type: bytes + returns: + descr: the 32byte random data + example: + request: [] + response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" eth_sign: descr: | diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 33a12dd98..cc8d4e93b 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifdef ETH_FULL #include "../../third-party/tommath/tommath.h" @@ -546,6 +547,40 @@ static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { return IN3_OK; } +static in3_ret_t in3_createKey(in3_rpc_handle_ctx_t* ctx) { + bytes_t seed = bytes(NULL, 0); + bytes32_t hash; + FILE* r = NULL; + if (d_len(ctx->params) == 1) { + CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) + keccak(d_to_bytes(ctx->params + 1), hash); + srand(bytes_to_int(hash, 4)); + } + else { +#ifndef WASM + r = fopen("/dev/urandom", "r"); + if (r) { + for (int i = 0; i < 32; i++) hash[i] = (uint8_t) fgetc(r); + fclose(r); + } + else +#endif + srand(current_ms() % 0xFFFFFFFF); + } + + if (!r) { +#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) + unsigned int number; + for (int i = 0; i < 32; i++) { + hash[i] = (rand_s(&number) ? rand() : (int) number) % 256; + } +#else + for (int i = 0; i < 32; i++) hash[i] = rand() % 256; +#endif + } + return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); +} + static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) d_token_t* tx_data = ctx->params + 1; @@ -611,6 +646,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("in3_decryptKey", in3_decryptKey(ctx)) TRY_RPC("in3_prepareTx", in3_prepareTx(ctx)) TRY_RPC("in3_signTx", in3_signTx(ctx)) + TRY_RPC("in3_createKey", in3_createKey(ctx)) return IN3_EIGNORE; } diff --git a/c/src/cmd/in3/CMakeLists.txt b/c/src/cmd/in3/CMakeLists.txt index 816096a30..bacaed17d 100644 --- a/c/src/cmd/in3/CMakeLists.txt +++ b/c/src/cmd/in3/CMakeLists.txt @@ -45,7 +45,18 @@ if (MULTISIG) set(LIBS ${LIBS} multisig) endif() -add_executable(in3 main.c in3_storage.c ../../tools/recorder/recorder.c) +add_executable(in3 + helper.c + main2.c + option_handler.c + rpc_handler.c + req_exec.c + transport.c + tx.c + weights.c + in3_storage.c + ../../tools/recorder/recorder.c +) target_compile_definitions(in3 PRIVATE _XOPEN_SOURCE=600) target_link_libraries(in3 init pk_signer ${LIBS} -lm) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index aa103ab03..53c560f3c 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -1,3 +1,9 @@ +// This is a generated file, please don't edit it manually! + +#include + +const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; + const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ --finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ @@ -115,6 +121,8 @@ pk2public \n\ ecrecover \n\ extracts the address and public key from a signature\n\ \n\ +createKey generates a new private key. See in3_createKey.\n\ + \n\ key \n\ reads the private key from JSON-Keystore file and returns the private key.\n\ \n\ diff --git a/c/src/cmd/in3/handlers.h b/c/src/cmd/in3/handlers.h index 719f85dc6..355c0ec6e 100644 --- a/c/src/cmd/in3/handlers.h +++ b/c/src/cmd/in3/handlers.h @@ -1,6 +1,6 @@ #include "../../core/client/plugin.h" bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char** argv); - +bool handle_rpc(in3_t* c, char** method, sb_t* params, int argc, char** argv); void init_env(in3_t* c, int argc, char* argv[]); void init_recorder(int* argc, char*** argv); \ No newline at end of file diff --git a/c/src/cmd/in3/helper.c b/c/src/cmd/in3/helper.c index 4576f3fc8..e983598b1 100644 --- a/c/src/cmd/in3/helper.c +++ b/c/src/cmd/in3/helper.c @@ -36,13 +36,20 @@ * simple commandline-util sending in3-requests. * */ #include "helper.h" +#include "../../api/eth1/abi.h" +#include "../../api/eth1/eth_api.h" +#include "../../signer/pk-signer/signer.h" +#include "../../tools/recorder/recorder.h" +#include "args.h" #include "handlers.h" +#include "transport.h" +#include "tx.h" #ifndef IN3_VERSION #define IN3_VERSION "local" #endif -_Noreturn void die(char* msg) { +void die(char* msg) { recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); recorder_exit(EXIT_FAILURE); } @@ -52,6 +59,10 @@ void print_hex(uint8_t* data, int len) { recorder_print(0, "\n"); } +const char* get_help_args() { + return help_args; +} + // helper to read the password from tty void read_pass(char* pw, int pwsize) { int i = 0, ch = 0; @@ -68,19 +79,26 @@ void read_pass(char* pw, int pwsize) { recorder_print(1, COLORT_RESETHIDDEN); //reveal typing } +static bool is_number(char* val) { + for (; *val; val++) { + if (*val > '9' || *val < '0') return false; + } + return true; +} + void configure_opt(in3_t* c, char* name, char* value, int argc, char** argv) { sb_t sb = {0}; // handle options if (handle_option(c, name, value, &sb, argc, argv)) return; - if (sb.data) { + if (!sb.data) { char* p = strtok(name, "."); sb_add_char(&sb, '{'); int b = 1; while (p) { char* next = strtok(NULL, "."); if (!next) { - if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) + if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0 || is_number(value)) sb_print(&sb, "\"%s\":%s", p, value); else sb_print(&sb, "\"%s\":\"%s\"", p, value); @@ -104,47 +122,62 @@ void configure_opt(in3_t* c, char* name, char* value, int argc, char** argv) { void configure(in3_t* c, char* name, char* value) { configure_opt(c, name, value, 0, NULL); } +static bool is_bool_opt(char* name) { + for (int i = 0; bool_props[i]; i++) { + if (strcmp(bool_props[i], name) == 0) return true; + } + return false; +} bool configure_arg(in3_t* c, char** args, int* index, int argc) { - if (arg[0] != '-') return false; const char* arg = args[*index]; char* value = strchr(arg, '='); char* name = NULL; + if (arg[0] != '-') return false; if (arg[1] && arg[1] != '-') { for (int i = 0; aliases[i]; i += 2) { if (strcmp(aliases[i], arg + 1) == 0) { - name = alloca(strlen(aliases[i + 1]) + 3); - name[0] = (name[1] = '-'); - strcpy(name + 2, aliases[i + 1]); - value = strchr(name, '='); - if (!value) { - if (argc - 1 <= *index) die("missing value for option"); - *index += 1; - value = args[*index]; + name = alloca(strlen(aliases[i + 1]) + 1); + strcpy(name, aliases[i + 1]); + value = strchr(aliases[i + 1], '='); + if (value) { + *strchr(name, '=') = 0; + value++; } - else - *value = 0; break; } } - if (!name) die("unknown option!"); + if (!name) { + char* err = alloca(strlen(arg) + 200); + sprintf(err, "Unknown option '%s'!", arg); + die(err); + } } + else if (arg[1] != '-') + return false; - if (!value) { - value = "true"; - name = alloca(strlen(arg) + 1); - strcpy(name, arg); - } - else { - value++; - if (!name) { - name = alloca(value - arg); - strncpy(name, arg, value - arg - 1); + if (!name) { + if (value) { + value++; + name = alloca(value - arg - 2); + strncpy(name, arg + 2, value - arg - 3); name[value - arg - 1] = 0; } + else { + name = alloca(strlen(arg) - 1); + strcpy(name, arg + 2); + } + } + + if (!value) { + if (is_bool_opt(name)) + value = "true"; + else { + if (argc - 1 <= *index) die("missing value for option"); + *index += 1; + value = args[*index]; + } } - if (name[0] == '-' && name[1] == '-') name += 2; - if (!value) return false; configure_opt(c, name, value, argc, args); return true; } @@ -289,7 +322,7 @@ void read_pk(char* pk_file, char* pwd, in3_t* c, char* method) { uint8_t* pk_seed = malloc(32); if (decrypt_key(key_json->result, pwd, pk_seed)) die("Invalid key"); - if (!method || strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0) { + if (!c && method && (strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0)) { char tmp[64]; bytes_to_hex(pk_seed, 32, tmp); recorder_print(0, "0x%s\n", tmp); @@ -305,7 +338,7 @@ char* get_argument(int argc, char* argv[], char* alias, char* arg, bool has_valu for (int i = 1; i < argc; i++) { if (alias && strcmp(alias, argv[i]) == 0) return has_value ? (i + 1 < argc ? argv[i + 1] : NULL) : argv[i]; - if (strncmp(arg, argv[i], l)) { + if (strncmp(arg, argv[i], l) == 0) { if (argv[i][l] == 0) return has_value ? (i + 1 < argc ? argv[i + 1] : NULL) : argv[i]; else if (argv[i][l] == '=') @@ -315,7 +348,52 @@ char* get_argument(int argc, char* argv[], char* alias, char* arg, bool has_valu return NULL; } -uint32_t* get_output_conf() { - static uint32_t conf = 0; +static uint32_t conf = 0; +uint32_t* get_output_conf() { return &conf; +} + +void display_result(char* method, char* result) { + // if the result is a string, we remove the quotes + if ((conf & out_human) == 0 && result[0] == '"' && result[strlen(result) - 1] == '"') { + memmove(result, result + 1, strlen(result)); + result[strlen(result) - 1] = 0; + } + + abi_sig_t* req = get_txdata()->abi_sig; + + // if the request was a eth_call, we decode the result + if (req) { + int l = strlen(result) / 2 - 1; + if (l) { + char* error = NULL; + uint8_t* tmp = alloca(l + 1); + json_ctx_t* res = abi_decode(req, bytes(tmp, hex_to_bytes(result, -1, tmp, l + 1)), &error); + if (error) die(error); + if (conf & out_json) + recorder_print(0, "%s\n", d_create_json(res, res->result)); + else + print_val(res->result); + } + // if not we simply print the result + } + else if (conf & out_human) { + json_ctx_t* jctx = parse_json(result); + if (jctx) + print_val(jctx->result); + else + recorder_print(0, "%s\n", result); + } + else if (is_onlyshow_rawtx() && strcmp(method, "in3_prepareTx") == 0 && get_txdata()->from) + recorder_print(0, "%s %s\n", result, get_txdata()->from); + else { + if (conf & out_eth && result[0] == '0' && result[1] == 'x' && strlen(result) <= 18) { + double val = char_to_long(result, strlen(result)); + recorder_print(0, "%.3f\n", val / 1000000000000000000L); + } + else if ((conf & out_hex) == 0 && result[0] == '0' && result[1] == 'x' && strlen(result) <= 18) + recorder_print(0, "%" PRIu64 "\n", char_to_long(result, strlen(result))); + else + recorder_print(0, "%s\n", result); + } } \ No newline at end of file diff --git a/c/src/cmd/in3/helper.h b/c/src/cmd/in3/helper.h index 4004c4e69..ca41f23b1 100644 --- a/c/src/cmd/in3/helper.h +++ b/c/src/cmd/in3/helper.h @@ -1,3 +1,11 @@ + +#ifndef MAIN_HELPER_H +#define MAIN_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + #include "../../core/client/keys.h" #include "../../core/client/plugin.h" #include "../../core/client/version.h" @@ -7,6 +15,7 @@ #include "../../core/util/debug.h" #include "../../core/util/log.h" #include "../../core/util/mem.h" +#include "../../tools/recorder/recorder.h" #include #include #include @@ -37,8 +46,8 @@ void print_val(d_token_t* t); char* get_argument(int argc, char* argv[], char* alias, char* arg, bool has_value); -uint32_t* get_output_conf(); - +uint32_t* get_output_conf(); +const char* get_help_args(); typedef enum output { out_human = 1, out_hex = 2, @@ -46,3 +55,10 @@ typedef enum output { out_eth = 8, out_debug = 16 } output_t; + +void display_result(char* method, char* result); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml index 62ae610bf..e8c0d8afb 100644 --- a/c/src/cmd/in3/in3.yml +++ b/c/src/cmd/in3/in3.yml @@ -228,6 +228,9 @@ rpc: extracts the address and public key from a signature + createKey: | + generates a new private key. See in3_createKey. + key: | reads the private key from JSON-Keystore file and returns the private key. diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index b4e3079db..820b481ab 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -58,6 +58,7 @@ #endif #include "../../core/client/keys.h" #include "../../core/client/plugin.h" +#include "../../core/client/request_internal.h" #include "../../core/client/version.h" #include "../../core/util/colors.h" #include "../../nodeselect/full/cache.h" @@ -609,7 +610,7 @@ static in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, voi #elif TRANSPORTS in3_ret_t r = send_http(NULL, action, plugin_ctx); #else - in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; + in3_ret_t r = req_set_error(req->req, "No transport supported in the client", IN3_ECONFIG); #endif if (action != PLGN_ACT_TRANSPORT_CLEAN) { last_response = b_new((uint8_t*) req->req->raw_response[0].data.data, req->req->raw_response[0].data.len); @@ -1352,9 +1353,6 @@ int main(int argc, char* argv[]) { } in3_log_debug("..sending request %s %s\n", method, args->data); -#ifdef NODESELECT_DEF - in3_chain_t* chain = &c->chain; -#endif if (wait && strcmp(method, "eth_sendTransaction") == 0) method = "eth_sendTransactionAndWait"; @@ -1374,7 +1372,8 @@ int main(int argc, char* argv[]) { in3_client_rpc_raw(c, sb->data, &result, &error); #ifdef NODESELECT_DEF - in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); + in3_chain_t* chain = &c->chain; + in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); // Update nodelist if a newer latest block was reported if (chain && nl->nodelist_upd8_params && nl->nodelist_upd8_params->exp_last_block) { char *r = NULL, *e = NULL; diff --git a/c/src/cmd/in3/main2.c b/c/src/cmd/in3/main2.c index 423b4384e..805462e66 100644 --- a/c/src/cmd/in3/main2.c +++ b/c/src/cmd/in3/main2.c @@ -1,9 +1,39 @@ +#include "../../init/in3_init.h" +#include "../../nodeselect/full/nodelist.h" +#include "../../nodeselect/full/nodeselect_def.h" #include "handlers.h" #include "helper.h" #include "req_exec.h" #include "transport.h" #include "tx.h" +static void send_request(in3_t* c, int argc, char** argv, char* method, sb_t* args, char** result, char** error) { + sb_t* sb = sb_new("{\"method\":\""); + sb_add_chars(sb, method); + sb_add_chars(sb, "\",\"params\":"); + sb_add_chars(sb, args->data); + char* ms_sigs = get_argument(argc, argv, "-sigs", "--ms.signatures", true); + if (ms_sigs) { + sb_add_chars(sb, ",\"in3\":{\"msSigs\":\""); + sb_add_chars(sb, ms_sigs); + sb_add_chars(sb, "\"}}"); + } + else + sb_add_chars(sb, "}"); + in3_client_rpc_raw(c, sb->data, result, error); + check_last_output(); +#ifdef NODESELECT_DEF + in3_chain_t* chain = &c->chain; + in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); + // Update nodelist if a newer latest block was reported + if (chain && nl->nodelist_upd8_params && nl->nodelist_upd8_params->exp_last_block) { + char *r = NULL, *e = NULL; + if (chain->type == CHAIN_ETH) + in3_client_rpc(c, "eth_blockNumber", "[]", &r, &e); + } +#endif +} + int main(int argc, char* argv[]) { // we want to verify all in3_log_set_level(LOG_INFO); @@ -19,7 +49,9 @@ int main(int argc, char* argv[]) { // parse arguments for (int i = 1; i < argc; i++) { + // is it a argument? if (configure_arg(c, argv, &i, argc)) continue; + // now handle arguments for special methods if (method == NULL) method = argv[i]; @@ -42,10 +74,22 @@ int main(int argc, char* argv[]) { } sb_add_char(args, ']'); + // start the server? if (!method) check_server(c); + // handle special cmd-methods + if (handle_rpc(c, &method, args, argc, argv)) recorder_exit(0); + // execute + in3_log_debug("..sending request %s %s\n", method, args->data); char *result = NULL, *error = NULL; + send_request(c, argc, argv, method, args, &result, &error); - check_last_output(); + if (error) + die(error); + else if (!result) + die("No result"); + else + display_result(method, result); + recorder_exit(0); } \ No newline at end of file diff --git a/c/src/cmd/in3/option_handler.c b/c/src/cmd/in3/option_handler.c index fe8e91e8f..c3736144f 100644 --- a/c/src/cmd/in3/option_handler.c +++ b/c/src/cmd/in3/option_handler.c @@ -1,10 +1,16 @@ -#include "args.h" +#include "../../nodeselect/full/nodelist.h" +#include "../../nodeselect/full/nodeselect_def.h" +#include "../../signer/multisig/multisig.h" +#include "../../signer/pk-signer/signer.h" + #include "handlers.h" #include "helper.h" +#include "in3_storage.h" #include "req_exec.h" #include "transport.h" #include "tx.h" #include "weights.h" + #define CHECK_OPTION(name, fn) \ if (strcmp(key, name) == 0) return fn; #ifndef IN3_VERSION @@ -12,7 +18,7 @@ #endif static bool set_chainId(char* value, sb_t* conf) { - if (strstr(id, "://") == NULL) return false; + if (strstr(value, "://") == NULL) return false; sb_add_chars(conf, "{\"rpc\":\""); sb_add_escaped_chars(conf, value); sb_add_chars(conf, "\"}"); @@ -20,7 +26,7 @@ static bool set_chainId(char* value, sb_t* conf) { } bool show_help() { - recorder_print(0, "Usage: in3 method ... \n\n%s", name, help_args); + recorder_print(0, "Usage: in3 method ... \n\n%s", get_help_args()); recorder_exit(0); return true; } @@ -52,7 +58,7 @@ bool show_version() { } #ifdef NODESELECT_DEF -static void set_nodelist(in3_t* c, char* nodes, sb_t* sb, bool update) { +static bool set_nodelist(in3_t* c, char* nodes, sb_t* sb, bool update) { if (!update) c->flags = FLAGS_STATS | FLAGS_BOOT_WEIGHTS | (c->flags & FLAGS_ALLOW_EXPERIMENTAL); char* cpy = alloca(strlen(nodes) + 1); in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); @@ -116,20 +122,20 @@ static bool set_uint32(uint32_t* dst, char* value) { static bool set_create2(char* value, sb_t* sb) { if (strlen(value) != 176) die("create2-arguments must have the form -zc2 ::"); char tmp[177], t2[500]; - memcpy(tmp, c2val, 177); + memcpy(tmp, value, 177); tmp[42] = tmp[109] = 0; sprintf(t2, "{\"zksync\":{\"signer_type\":\"create2\",\"create2\":{\"creator\":\"%s\",\"codehash\":\"%s\",\"saltarg\":\"%s\"}}}", tmp, tmp + 43, tmp + 110); sb_add_chars(sb, t2); return false; } -static bool set_recorder(in3_t* c, char* value, sb_t* conf, int argc, char** argv, bool write) { +static bool set_recorder(in3_t* c, char* value, int argc, char** argv, bool write) { if (write) recorder_write_start(c, value, argc, argv); else recorder_read_start(c, value); return true; } -static bool set_pk(in3_t* c, char* value, sb_t* conf, int argc, char** argv) { +static bool set_pk(in3_t* c, char* value, int argc, char** argv) { if (value[0] != '0' || value[1] != 'x') { read_pk(value, get_argument(argc, argv, "-pwd", "--password", true), c, NULL); return true; @@ -189,14 +195,15 @@ bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char* CHECK_OPTION("nonce", set_uint64(&get_txdata()->nonce, value)) CHECK_OPTION("wait", set_uint32(&get_txdata()->wait, "1")) CHECK_OPTION("block", set_string(&get_txdata()->block, value)) + CHECK_OPTION("block", set_data(value)) CHECK_OPTION("value", set_string(&get_txdata()->value, get_wei(value))) CHECK_OPTION("zksync.create2", set_create2(value, conf)) CHECK_OPTION("test-request", set_flag(get_weightsdata(), weight_test_request, value)) CHECK_OPTION("test-health-request", set_flag(get_weightsdata(), weight_health, value)) - CHECK_OPTION("response.in", set_recorder(c, value, conf, argc, argv, false)) - CHECK_OPTION("response.out", set_recorder(c, value, conf, argc, argv, true)) - CHECK_OPTION("file.in", set_recorder(c, value, conf, argc, argv, false)) - CHECK_OPTION("file.out", set_recorder(c, value, conf, argc, argv, true)) + CHECK_OPTION("response.in", set_response_file(true)) + CHECK_OPTION("response.out", set_response_file(false)) + CHECK_OPTION("file.in", set_recorder(c, value, argc, argv, false)) + CHECK_OPTION("file.out", set_recorder(c, value, argc, argv, true)) CHECK_OPTION("ms.signatures", true) CHECK_OPTION("multisig", set_ms(c, value)) CHECK_OPTION("human", set_flag(get_output_conf(), out_human, value)) @@ -204,15 +211,15 @@ bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char* CHECK_OPTION("hex", set_flag(get_output_conf(), out_hex, value)) CHECK_OPTION("json", set_flag(get_output_conf(), out_json, value)) CHECK_OPTION("quiet", set_quiet()) - CHECK_OPTION("port", set_uint32(&get_req_exec()->port, value)) + CHECK_OPTION("port", set_string(&get_req_exec()->port, value)) CHECK_OPTION("allowed-methods", set_string(&get_req_exec()->allowed_methods, value)) CHECK_OPTION("onlysign", set_onlyshow_rawtx()) - CHECK_OPTION("sigtype", set_string((&get_txdata()->signtype,value)) + CHECK_OPTION("sigtype", set_string(&get_txdata()->signtype, value)) CHECK_OPTION("debug", set_debug()) #ifdef NODESELECT_DEF - CHECK_OPTION("nodelist", set_nodelist(value, conf, false)) - CHECK_OPTION("bootnodes", set_nodelist(value, conf, true)) - CHECK_OPTION("pk", set_pk(c, value, conf, argc, argv)) + CHECK_OPTION("nodelist", set_nodelist(c, value, conf, false)) + CHECK_OPTION("bootnodes", set_nodelist(c, value, conf, true)) + CHECK_OPTION("pk", set_pk(c, value, argc, argv)) #endif #ifdef LEDGER_NANO CHECK_OPTION("path", set_path(c, valuev)) diff --git a/c/src/cmd/in3/req_exec.c b/c/src/cmd/in3/req_exec.c index cdeb4f370..a7d44de4a 100644 --- a/c/src/cmd/in3/req_exec.c +++ b/c/src/cmd/in3/req_exec.c @@ -1,7 +1,7 @@ #include "req_exec.h" +#include "../../tools/recorder/recorder.h" #include "../http-server/http_server.h" #include "helper.h" - req_exec_t* get_req_exec() { static req_exec_t val = {0}; return &val; @@ -78,10 +78,15 @@ void check_server(in3_t* c) { if (get_req_exec()->port) { #ifdef IN3_SERVER // start server - http_run_server(port, c, allowed_methods); + http_run_server(get_req_exec()->port, c, get_req_exec()->allowed_methods); recorder_exit(0); #else die("You need to compile in3 with -DIN3_SERVER=true to start the server."); #endif } + else { + in3_log_info("in3 " IN3_VERSION " - reading json-rpc from stdin. (exit with ctrl C)\n________________________________________________\n"); + execute(c, stdin); + recorder_exit(0); + } } \ No newline at end of file diff --git a/c/src/cmd/in3/req_exec.h b/c/src/cmd/in3/req_exec.h index 5e12f2539..2de336573 100644 --- a/c/src/cmd/in3/req_exec.h +++ b/c/src/cmd/in3/req_exec.h @@ -1,8 +1,8 @@ #include "helper.h" typedef struct req_exec { - uint32_t port; - char* allowed_methods; + char* port; + char* allowed_methods; } req_exec_t; req_exec_t* get_req_exec(); diff --git a/c/src/cmd/in3/rpc_handler.c b/c/src/cmd/in3/rpc_handler.c index e69de29bb..008eea2ff 100644 --- a/c/src/cmd/in3/rpc_handler.c +++ b/c/src/cmd/in3/rpc_handler.c @@ -0,0 +1,129 @@ +#include "../../api/eth1/abi.h" +#include "../../api/eth1/eth_api.h" +#include "../../api/ipfs/ipfs_api.h" +#include "helper.h" +#include "transport.h" +#include "tx.h" +#include "weights.h" +#define CHECK_RPC(name, fn) \ + if (strcmp(*method, name) == 0) return fn; + +static bool decode_keystore(char* args, int argc, char** argv) { + json_ctx_t* ctx = parse_json(args); + if (d_len(ctx->result) != 1 || d_type(ctx->result + 1) != T_STRING) die("decoding a key expects one argument with the filename of the keystorefile."); + read_pk(d_get_string_at(ctx->result, 0), get_argument(argc, argv, "-pwd", "--password", true), NULL, "key"); + json_free(ctx); + return true; +} +static bool _call(in3_t* c, char** method, sb_t* params) { + encode_abi(c, params); + *method = "eth_call"; + return false; +} +static bool _send(in3_t* c, char** method, sb_t* params) { + encode_abi(c, params); + if (is_onlyshow_rawtx() && (c->plugin_acts & (PLGN_ACT_SIGN | PLGN_ACT_SIGN_ACCOUNT)) == 0) + *method = "in3_prepareTx"; + else + *method = get_txdata()->wait ? "eth_sendTransactionAndWait" : "eth_sendTransaction"; + return false; +} + +static bool _sign(sb_t* params) { + params->len = 0; + bytes_t* data = get_txdata()->data; + if (data->len > 2 && data->data[0] == '0' && data->data[1] == 'x') + data = hex_to_new_bytes((char*) data->data + 2, data->len - 2); + sb_add_rawbytes(params, "[\"0x", *data, 0); + sb_add_chars(params, "\",NULL,\""); + sb_add_chars(params, get_txdata()->signtype ? get_txdata()->signtype : "raw"); + sb_add_chars(params, "\"]"); + if (data != get_txdata()->data) b_free(data); + return false; +} + +static bool _autocompletelist() { + recorder_print(0, "send call abi_encode abi_decode ipfs_get ipfs_put ecrecover key -sigtype -st eth_sign raw hash sign createkey -ri -ro keystore unlock pk2address pk2public mainnet goerli ewc btc ipfs local true false latest -np -debug -c -chain -p -version -proof -s -signs -b -block -to -d -data -gas_limit -value -w -wait -hex -json in3_nodeList in3_stats in3_sign web3_clientVersion web3_sha3 net_version net_peerCount net_listening eth_protocolVersion eth_syncing eth_coinbase eth_mining eth_hashrate eth_gasPrice eth_accounts eth_blockNumber eth_getBalance eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getCode eth_sign eth_sendTransaction eth_sendRawTransaction eth_call eth_estimateGas eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockHashAndIndex eth_getTransactionByBlockNumberAndIndex eth_getTransactionReceipt eth_pendingTransactions eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileLLL eth_compileSolidity eth_compileSerpent eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_getWork eth_submitWork eth_submitHashrate in3_cacheClear\n"); + return true; +} + +static bool _abi_encode(sb_t* args) { + char* error = NULL; + json_ctx_t* in_data = parse_json(args->data); + if (!in_data) die("invalid params"); + if (!get_txdata()->sig) die("missing signature"); + abi_sig_t* s = abi_sig_create(get_txdata()->sig, &error); + if (s && !error) { + bytes_t data = abi_encode(s, in_data->result, &error); + if (data.data) + print_hex(data.data, data.len); + abi_sig_free(s); + } + if (error) die(error); + return true; +} + +static bool _abi_decode(sb_t* args) { + char* error = NULL; + json_ctx_t* in_data = parse_json(args->data); + if (!in_data) die("invalid params"); + if (!get_txdata()->sig) die("missing signature"); + abi_sig_t* s = abi_sig_create(get_txdata()->sig, &error); + if (s && !error) { + bytes_t data = d_to_bytes(d_get_at(parse_json(args->data)->result, 0)); + json_ctx_t* res = abi_decode(s, data, &error); + if (error) die(error); + if (*get_output_conf() & out_json) + recorder_print(0, "%s\n", d_create_json(res, res->result)); + else + print_val(res->result); + abi_sig_free(s); + } + if (error) die(error); + return true; +} + +static bool _ipfs_get(in3_t* c, sb_t* args) { + if (c->chain.type != CHAIN_IPFS) configure(c, "chainId", "ipfs"); + int size = args->len; + if (size == 2 || args->data[1] != '"' || size < 20 || strstr(args->data + 2, "\"") == NULL) die("missing ipfs hash"); + args->data[size - 2] = 0; +#ifdef IPFS + bytes_t* content = ipfs_get(c, args->data + 2); +#else + die("ipfs is not supported. Please compile with -DIPFS=true"); +#endif + if (!content) die("IPFS hash not found!"); + fwrite(content->data, content->len, 1, stdout); + fflush(stdout); + return true; +} + +static bool _ipfs_put(in3_t* c, sb_t* args) { + if (c->chain.type != CHAIN_IPFS) configure(c, "chainId", "ipfs"); + args->len = 0; + sb_add_rawbytes(args, "[\"0x", readFile(stdin), 0); + sb_add_chars(args, "\",\"hex\"]"); + return false; +} + +bool handle_rpc(in3_t* c, char** method, sb_t* params, int argc, char** argv) { + CHECK_RPC("key", decode_keystore(params->data, argc, argv)) + CHECK_RPC("call", _call(c, method, params)) + CHECK_RPC("abi_encode", _abi_encode(params)) + CHECK_RPC("abi_decode", _abi_decode(params)) + CHECK_RPC("ipfs_get", _ipfs_get(c, params)) + CHECK_RPC("ipfs_put", _ipfs_put(c, params)) + CHECK_RPC("in3_weights", exec_weights(c)) + CHECK_RPC("send", _send(c, method, params)) + CHECK_RPC("sign", _sign(params)) + CHECK_RPC("autocompletelist", _autocompletelist()) + CHECK_RPC("createKey", (*method = "in3_createKey") == NULL) + CHECK_RPC("pk2address", (*method = "in3_pk2address") == NULL) + CHECK_RPC("pk2public", (*method = "in3_pk2public") == NULL) + CHECK_RPC("ecrecover", (*method = "in3_ecrecover") == NULL) + if (get_txdata()->wait) { + CHECK_RPC("eth_sendTransaction", (*method = "eth_sendTransactionAndWait") == NULL) + } + return false; +} \ No newline at end of file diff --git a/c/src/cmd/in3/transport.c b/c/src/cmd/in3/transport.c index e6ceca58c..fb5da4d21 100644 --- a/c/src/cmd/in3/transport.c +++ b/c/src/cmd/in3/transport.c @@ -17,7 +17,7 @@ in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void in3_http_request_t* req = plugin_ctx; if (action == PLGN_ACT_TRANSPORT_SEND) { #ifndef DEBUG - if (debug_mode) + if (*get_output_conf() & out_debug) fprintf(stderr, "send request to %s: \n" COLORT_RYELLOW "%s" COLORT_RESET "\n", req->urls_len ? req->urls[0] : "none", req->payload); #endif if (in_response.len) { @@ -42,12 +42,12 @@ in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void #elif TRANSPORTS in3_ret_t r = send_http(NULL, action, plugin_ctx); #else - in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; + in3_ret_t r = req_set_error(req->req, "No transport supported in the client", IN3_ECONFIG); #endif if (action != PLGN_ACT_TRANSPORT_CLEAN) { last_response = b_new((uint8_t*) req->req->raw_response[0].data.data, req->req->raw_response[0].data.len); #ifndef DEBUG - if (debug_mode) { + if (*get_output_conf() & out_debug) { if (req->req->raw_response[0].state == IN3_OK) fprintf(stderr, "success response \n" COLORT_RGREEN "%s" COLORT_RESET "\n", req->req->raw_response[0].data.data); else @@ -91,6 +91,7 @@ void init_transport(in3_t* c) { bool set_test_transport(in3_t* c, char* name) { test_name = name; in3_plugin_register(c, PLGN_ACT_TRANSPORT, test_transport, NULL, true); + return true; } bool set_onlyshow_rawtx() { @@ -98,11 +99,16 @@ bool set_onlyshow_rawtx() { return true; } -bool set_response_file(bool is_ine) { +bool is_onlyshow_rawtx() { + return only_show_raw_tx; +} + +bool set_response_file(bool is_in) { if (is_in) in_response = readFile(stdin); else out_response = true; + return true; } void check_last_output() { diff --git a/c/src/cmd/in3/transport.h b/c/src/cmd/in3/transport.h index cd7d5f20b..e80b5e432 100644 --- a/c/src/cmd/in3/transport.h +++ b/c/src/cmd/in3/transport.h @@ -5,5 +5,6 @@ in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void* plug void init_transport(in3_t* c); bool set_test_transport(in3_t* c, char* name); bool set_onlyshow_rawtx(); -bool set_response_file(bool is_in, char* value); +bool is_onlyshow_rawtx(); +bool set_response_file(bool is_in); void check_last_output(); \ No newline at end of file diff --git a/c/src/cmd/in3/tx.c b/c/src/cmd/in3/tx.c index 8e2f0ab47..fd2b73e4d 100644 --- a/c/src/cmd/in3/tx.c +++ b/c/src/cmd/in3/tx.c @@ -1,13 +1,13 @@ #include "tx.h" #include "helper.h" +static tx_t _tx = {0}; tx_t* get_txdata() { - static tx_t _tx = {0}; return &_tx; } // prepare a eth_call or eth_sendTransaction -abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data, char* from) { +static abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data, char* from) { char* error = NULL; bytes_t rdata = {0}; abi_sig_t* req = fn_sig ? abi_sig_create(fn_sig, &error) : NULL; // only if we have a function signature, we will parse it and create a call_request. @@ -77,3 +77,7 @@ abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, ui sb_free(params); return req; } + +void encode_abi(in3_t* c, sb_t* args) { + _tx.abi_sig = prepare_tx(_tx.sig, resolve(c, _tx.to), args, _tx.block, _tx.gas, _tx.gas_price, _tx.value, _tx.data, _tx.from); +} \ No newline at end of file diff --git a/c/src/cmd/in3/tx.h b/c/src/cmd/in3/tx.h index cecb7e933..6b3a7a0e4 100644 --- a/c/src/cmd/in3/tx.h +++ b/c/src/cmd/in3/tx.h @@ -1,18 +1,20 @@ +#include "../../api/eth1/abi.h" #include "helper.h" - typedef struct tx { - bytes_t* data; - char* block; - char* from; - char* to; - uint64_t gas; - uint64_t gas_price; - uint64_t nonce; - char* value; - uint32_t wait; - char* signtype; - char* sig; + bytes_t* data; + char* block; + char* from; + char* to; + uint64_t gas; + uint64_t gas_price; + uint64_t nonce; + char* value; + uint32_t wait; + char* signtype; + char* sig; + abi_sig_t* abi_sig; } tx_t; -tx_t* get_txdata(); \ No newline at end of file +tx_t* get_txdata(); +void encode_abi(in3_t* c, sb_t* args); \ No newline at end of file diff --git a/c/src/cmd/in3/weights.c b/c/src/cmd/in3/weights.c index 117341a21..7a6d367dd 100644 --- a/c/src/cmd/in3/weights.c +++ b/c/src/cmd/in3/weights.c @@ -1,7 +1,145 @@ #include "weights.h" +#include "../../nodeselect/full/nodelist.h" +#include "../../nodeselect/full/nodeselect_def.h" #include "helper.h" - -uint32_t* get_weightsdata() { - static uint32_t weightdata = 0; +#ifdef USE_CURL +#include "../../transport/curl/in3_curl.h" +#elif USE_WINHTTP +#include "../../transport/winhttp/in3_winhttp.h" +#else +#include "../../transport/http/in3_http.h" +#endif +static uint32_t weightdata = 0; +uint32_t* get_weightsdata() { return &weightdata; +} + +bool exec_weights(in3_t* c) { + int run_test_request = weightdata ? ((weightdata & weight_health) ? 2 : 1) : 0; + c->max_attempts = 1; + uint32_t block = 0, b = 0; + BIT_CLEAR(c->flags, FLAGS_AUTO_UPDATE_LIST); + uint64_t now = in3_time(NULL); + char* more = "WEIGHT"; + in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); + in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); + if (run_test_request == 1) more = "WEIGHT : LAST_BLOCK"; + if (run_test_request == 2) more = "WEIGHT : NAME VERSION : RUNNING : HEALTH : LAST_BLOCK"; + recorder_print(0, " : %-45s : %7s : %5s : %5s: %s\n------------------------------------------------------------------------------------------------\n", "URL", "BL", "CNT", "AVG", more); + for (unsigned int i = 0; i < nl->nodelist_length; i++) { + in3_req_t* ctx = NULL; + char* health_s = NULL; + if (run_test_request) { + char req[300]; + char adr[41]; + bytes_to_hex((nl->nodelist + i)->address, 20, adr); + sprintf(req, "{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"in3\":{\"dataNodes\":[\"0x%s\"]}}", adr); + ctx = req_new(c, req); + if (ctx) in3_send_req(ctx); + if (run_test_request == 2) { + int health = 1; + char* version = ""; + char* node_name = ""; + uint32_t running = 0; + json_ctx_t* health_res = NULL; + char health_url[500]; + char* urls[1]; + urls[0] = health_url; + sprintf(health_url, "%s/health", nl->nodelist[i].url); + in3_http_request_t r = {0}; + in3_req_t ctx = {0}; + ctx.raw_response = _calloc(sizeof(in3_response_t), 1); + ctx.raw_response->state = IN3_WAITING; + ctx.client = c; + r.req = &ctx; + r.urls = urls; + r.urls_len = 1; + r.payload = ""; +#ifdef USE_CURL + send_curl(NULL, PLGN_ACT_TRANSPORT_SEND, &r); +#elif USE_WINHTTP + send_winhttp(NULL, PLGN_ACT_TRANSPORT_SEND, &r); +#elif TRANSPORTS + send_http(NULL, PLGN_ACT_TRANSPORT_SEND, &r); +#endif + if (ctx.raw_response->state) + health = 0; + else { + health_res = parse_json(ctx.raw_response->data.data); + if (!health_res) + health = 0; + else { + node_name = d_get_string(health_res->result, key("name")); + version = d_get_string(health_res->result, key("version")); + running = d_get_int(health_res->result, key("running")); + char* status = d_get_string(health_res->result, key("status")); + if (!status || strcmp(status, "healthy")) health = 0; + } + } + if (version) { + char* l = strrchr(version, ':'); + if (l) version = l + 1; + } + health_s = _malloc(3000); + sprintf(health_s, "%-22s %-7s %7d %-9s ", node_name ? node_name : "-", version ? version : "-", running, health ? "OK" : "unhealthy"); + + if (ctx.raw_response->data.data) + _free(ctx.raw_response->data.data); + _free(ctx.raw_response); + if (health_res) json_free(health_res); + } + } + in3_node_t* node = nl->nodelist + i; + in3_node_weight_t* weight = nl->weights + i; + uint64_t blacklisted = weight->blacklisted_until > now ? weight->blacklisted_until : 0; + uint32_t calc_weight = in3_node_calculate_weight(weight, node->capacity, now); + char * tr = NULL, *warning = NULL; + if (ctx) { + tr = _malloc(1000); + if (!ctx->error && d_get(ctx->responses[0], K_ERROR)) { + d_token_t* msg = d_get(ctx->responses[0], K_ERROR); + if (d_type(msg) == T_OBJECT) msg = d_get(msg, K_MESSAGE); + sprintf((warning = tr), "%s", msg ? d_string(msg) : "Error-Response!"); + } + else if (!ctx->error) { + b = d_get_int(ctx->responses[0], K_RESULT); + if (block < b) block = b; + + if (b < block - 1) + sprintf((warning = tr), "#%i ( out of sync : %i blocks behind latest )", b, block - b); + else if (strncmp(node->url, "https://", 8)) + sprintf((warning = tr), "#%i (missing https, which is required in a browser )", b); + else if (!IS_APPROX(d_get_int(ctx->responses[0], K_RESULT), d_get_int(d_get(ctx->responses[0], K_IN3), K_CURRENT_BLOCK), 1)) + sprintf((warning = tr), "#%i ( current block mismatch: %i blocks apart )", b, + d_get_int(ctx->responses[0], K_RESULT) - d_get_int(d_get(ctx->responses[0], K_IN3), K_CURRENT_BLOCK)); + else + sprintf(tr, "#%i", b); + } + else if (!strlen(node->url) || !node->props) + sprintf((warning = tr), "No URL spcified anymore props = %i ", (int) (node->props & 0xFFFFFF)); + else if ((node->props & NODE_PROP_DATA) == 0) + sprintf((warning = tr), "The node is marked as not supporting Data-Providing"); + else if (c->proof != PROOF_NONE && (node->props & NODE_PROP_PROOF) == 0) + sprintf((warning = tr), "The node is marked as able to provide proof"); + else if ((c->flags & FLAGS_HTTP) && (node->props & NODE_PROP_HTTP) == 0) + sprintf((warning = tr), "The node is marked as able to support http-requests"); + else + tr = ctx->error; + if (strlen(tr) > 100) tr[100] = 0; + } + if (blacklisted) + recorder_print(0, COLORT_RED); + else if (warning) + recorder_print(0, COLORT_YELLOW); + else if (!weight->response_count) + recorder_print(0, COLORT_DARKGRAY); + else + recorder_print(0, COLORT_GREEN); + recorder_print(0, "%2i %-45s %7i %5i %5i %5i %s%s", i, node->url, (int) (blacklisted ? blacklisted - now : 0), weight->response_count, weight->response_count ? (weight->total_response_time / weight->response_count) : 0, calc_weight, health_s ? health_s : "", tr ? tr : ""); + recorder_print(0, COLORT_RESET "\n"); + if (tr && tr != ctx->error) _free(tr); + if (health_s) _free(health_s); + if (ctx) req_free(ctx); + } + return true; } \ No newline at end of file diff --git a/c/src/cmd/in3/weights.h b/c/src/cmd/in3/weights.h index c5ef65d25..0dd38d33c 100644 --- a/c/src/cmd/in3/weights.h +++ b/c/src/cmd/in3/weights.h @@ -1,8 +1,9 @@ #include "helper.h" -typedef enum output { +typedef enum weight_enum { weight_test_request = 1, weight_health = 2 -} output_t; +} weight_enum_t; -uint32_t* get_weightsdata(); \ No newline at end of file +uint32_t* get_weightsdata(); +bool exec_weights(in3_t* c); \ No newline at end of file diff --git a/c/src/tools/recorder/recorder.c b/c/src/tools/recorder/recorder.c index 4cf7ee0af..c83102352 100644 --- a/c/src/tools/recorder/recorder.c +++ b/c/src/tools/recorder/recorder.c @@ -282,7 +282,7 @@ void recorder_read_start(in3_t* c, char* file) { void recorder_update_cmd(char* file, int* argc, char** argv[]) { rec.f = fopen(file, "r"); if (!rec.f) { - fprintf(stderr, "Cannot open %s : %s\n", file, strerror((int) errno)); + fprintf(stderr, "Cannot open recordfile %s : %s\n", file, strerror((int) errno)); exit(EXIT_FAILURE); } recorder_entry_t* entry = next_entry("cmd", NULL); diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 577a54cbf..58f4ac903 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -43,6 +43,7 @@ subcmds=( 'eth_sendTransactionAndWait: signs and sends a Transaction, but then waits until the transaction receipt can be verified ' 'eth_sign: The sign method calculates an Ethereum specific signature with: ' 'eth_signTransaction: Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTrans... ' + 'in3_createKey: Generates 32 random bytes ' 'keccak: Returns Keccak-256 (not the standardized SHA3-256) of the given data' 'net_version: the Network Version (currently 1)' 'sha256: Returns sha-256 of the given data ' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index c23be640f..874556463 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -7,6 +7,7 @@ const rpc_doc = [] const config_doc = [] const main_help = [] const main_aliases = [] +const bool_props = [] let docs = {}, config = {}, types = {} const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) @@ -83,6 +84,7 @@ function handle_config(conf, pre, title, descr) { } } asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + (c.alias || (pre + key + (c.type == 'bool' ? '=true' : ''))) + '",')); + if (c.type == 'bool') bool_props.push(pre + key); main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(7) + short_descr(c.descr)) let s = '' if (c.descr) s += '[' + short_descr(c.descr) + ']' @@ -210,6 +212,6 @@ Object.keys(main_conf.rpc).forEach(k => { fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) -fs.writeFileSync('../c/src/cmd/in3/args.h', 'const char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) +fs.writeFileSync('../c/src/cmd/in3/args.h', '// This is a generated file, please don\'t edit it manually!\n\n#include \n\nconst char* bool_props[]={ ' + bool_props.map(_ => '"' + _ + '", ').join('') + ' NULL};\n\nconst char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) From 33a936002deef7374a337307a1d122385c9fd2f1 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 21:57:12 +0200 Subject: [PATCH 057/221] fix main --- c/src/api/eth1/rpc_api.c | 1 - c/src/cmd/in3/CMakeLists.txt | 2 +- c/src/cmd/in3/main.c | 1472 ++-------------------------------- c/src/cmd/in3/main2.c | 95 --- 4 files changed, 63 insertions(+), 1507 deletions(-) delete mode 100644 c/src/cmd/in3/main2.c diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index cc8d4e93b..5fae18d9c 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -548,7 +548,6 @@ static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_createKey(in3_rpc_handle_ctx_t* ctx) { - bytes_t seed = bytes(NULL, 0); bytes32_t hash; FILE* r = NULL; if (d_len(ctx->params) == 1) { diff --git a/c/src/cmd/in3/CMakeLists.txt b/c/src/cmd/in3/CMakeLists.txt index bacaed17d..41eec10fb 100644 --- a/c/src/cmd/in3/CMakeLists.txt +++ b/c/src/cmd/in3/CMakeLists.txt @@ -47,7 +47,7 @@ endif() add_executable(in3 helper.c - main2.c + main.c option_handler.c rpc_handler.c req_exec.c diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 820b481ab..805462e66 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -1,1366 +1,18 @@ -/******************************************************************************* - * This file is part of the Incubed project. - * Sources: https://github.com/blockchainsllc/in3 - * - * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC - * - * - * COMMERCIAL LICENSE USAGE - * - * Licensees holding a valid commercial license may use this file in accordance - * with the commercial license agreement provided with the Software or, alternatively, - * in accordance with the terms contained in a written agreement between you and - * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further - * information please contact slock.it at in3@slock.it. - * - * Alternatively, this file may be used under the AGPL license as follows: - * - * AGPL LICENSE USAGE - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Affero General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - * [Permissions of this strong copyleft license are conditioned on making available - * complete source code of licensed works and modifications, which include larger - * works using a licensed work, under the same license. Copyright and license notices - * must be preserved. Contributors provide an express grant of patent rights.] - * You should have received a copy of the GNU Affero General Public License along - * with this program. If not, see . - *******************************************************************************/ - -/** @file - * simple commandline-util sending in3-requests. - * */ -#include "../../api/eth1/abi.h" -#include "../../api/eth1/eth_api.h" -#include "../../api/ipfs/ipfs_api.h" -#include "../../core/util/bitset.h" -#include "../../core/util/data.h" -#include "../../core/util/debug.h" -#include "../../core/util/log.h" -#include "../../core/util/mem.h" -#include "../../third-party/crypto/ecdsa.h" -#include "../../third-party/crypto/rand.h" -#include "../../third-party/crypto/secp256k1.h" -#ifdef USE_CURL -#include "../../transport/curl/in3_curl.h" -#elif USE_WINHTTP -#include "../../transport/winhttp/in3_winhttp.h" -#else -#include "../../transport/http/in3_http.h" -#endif -#ifdef IN3_SERVER -#include "../http-server/http_server.h" -#endif -#include "../../core/client/keys.h" -#include "../../core/client/plugin.h" -#include "../../core/client/request_internal.h" -#include "../../core/client/version.h" -#include "../../core/util/colors.h" -#include "../../nodeselect/full/cache.h" -#include "../../nodeselect/full/nodelist.h" - -#if defined(LEDGER_NANO) -#include "../../signer/ledger-nano/signer/ethereum_apdu_client.h" -#include "../../signer/ledger-nano/signer/ethereum_apdu_client_priv.h" -#include "../../signer/ledger-nano/signer/ledger_signer.h" -#endif - #include "../../init/in3_init.h" +#include "../../nodeselect/full/nodelist.h" #include "../../nodeselect/full/nodeselect_def.h" -#include "../../signer/multisig/multisig.h" -#include "../../signer/pk-signer/signer.h" -#include "../../tools/recorder/recorder.h" -#include "../../verifier/eth1/nano/chainspec.h" -#include "args.h" -#include "in3_storage.h" -#include -#include -#include -#include -#include -#include - -#ifndef IN3_VERSION -#define IN3_VERSION "local" -#endif - -// helpstring -void show_help(char* name) { - recorder_print(0, "Usage: %s method ... \n\n%s", name, help_args); -} -_Noreturn static void die(char* msg) { - recorder_print(1, COLORT_RED "Error: %s" COLORT_RESET "\n", msg); - recorder_exit(EXIT_FAILURE); -} -static void _configure(in3_t* c, char* k, const char* p, char* val) { - char* pattern = alloca(strlen(val) + strlen(k) + strlen(p) + 8); - char* data = alloca(strlen(val) + strlen(k) + 8); - sprintf(pattern, "{\"%s\": %s}", "%s", p); - sprintf(data, pattern, k, val); - char* e = in3_configure(c, data); - if (e) { - char* tmp = alloca(strlen(data) + strlen(e) + 60); - sprintf(tmp, "Error configuring the client with config (%s): %s", data, e); - die(tmp); - } -} -static void _configure2(in3_t* c, char* k1, char* k2, const char* p, char* val) { - char* pattern = alloca(strlen(val) + strlen(k1) + strlen(k2) + 16); - char* data = alloca(strlen(val) + strlen(k1) + strlen(k2) + 16); - sprintf(pattern, "{\"%s\":{\"%s\" : %s}}", "%s", "%s", p); - sprintf(data, pattern, k1, k2, val); - char* e = in3_configure(c, data); - if (e) die(e); -} - -#define configure(s, p) _configure(c, s, "\"%s\"", p) -#define configure_2(s1, s2, p) _configure2(c, s1, s2, "\"%s\"", p) - -static bool debug_mode = false; -static void print_hex(uint8_t* data, int len) { - recorder_print(0, "0x"); - for (int i = 0; i < len; i++) recorder_print(0, "%02x", data[i]); - recorder_print(0, "\n"); -} -// helper to read the password from tty -void read_pass(char* pw, int pwsize) { - int i = 0, ch = 0; - recorder_print(1, COLORT_HIDDEN); //conceal typing and save position - while (true) { - ch = getchar(); - if (ch == '\r' || ch == '\n' || ch == EOF) break; //get characters until CR or NL - if (i < pwsize - 1) { //do not save pw longer than space in pw - pw[i] = ch; //longer pw can be entered but excess is ignored - pw[i + 1] = 0; - } - i++; - } - recorder_print(1, COLORT_RESETHIDDEN); //reveal typing -} - -static bool configure_arg(in3_t* c, char** args, int* index, int argc) { - UNUSED_VAR(index); - UNUSED_VAR(argc); - const char* arg = args[*index]; - char* value = strchr(arg, '='); - char* name = NULL; - if (arg[0] != '-') return false; - if (arg[1] && arg[1] != '-') { - for (int i = 0; aliases[i]; i += 2) { - if (strcmp(aliases[i], arg + 1) == 0) { - name = alloca(strlen(aliases[i + 1]) + 3); - name[0] = (name[1] = '-'); - strcpy(name + 2, aliases[i + 1]); - value = strchr(name, '='); - if (!value) { - if (argc - 1 <= *index) die("missing value for option"); - *index += 1; - value = args[*index]; - } - else - *value = 0; - break; - } - } - if (!name) die("unknown option!"); - } - - if (!value) { - // die("invalid syntax for --key=value"); - value = "true"; - name = alloca(strlen(arg) + 1); - strcpy(name, arg); - } - else { - value++; - if (!name) { - name = alloca(value - arg); - strncpy(name, arg, value - arg - 1); - name[value - arg - 1] = 0; - } - } - - if (name[0] == '-' && name[1] == '-') { - name += 2; - char* p = strtok(name, "."); - sb_t sb = {0}; - sb_add_char(&sb, '{'); - int b = 1; - while (p) { - char* next = strtok(NULL, "."); - if (!next) { - if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0) - sb_print(&sb, "\"%s\":%s", p, value); - else - sb_print(&sb, "\"%s\":\"%s\"", p, value); - break; - } - b++; - sb_print(&sb, "\"%s\":{", p); - p = next; - continue; - } - for (; b; b--) sb_add_char(&sb, '}'); - - // printf("_configure\n"); - // in3_log_info("configure %s\n", sb.data); - char* error = in3_configure(c, sb.data); - if (error) - die(error); - return true; - } - return false; -} - -// accepts a value as -// 0.1eth -// 2keth -// 2.3meth -char* get_wei(char* val) { - if (*val == '0' && val[1] == 'x') return val; - bytes32_t tmp; - int s = string_val_to_bytes(val, NULL, tmp); - if (s < 0) die("Invalid numeric value"); - char* res = _malloc(s * 2 + 3); - bytes_to_hex(tmp, s, res + 2); - if (res[2] == '0') res++; - res[0] = '0'; - res[1] = 'x'; - return res; -} -static void execute(in3_t* c, FILE* f) { - if (feof(f)) die("no data"); - sb_t* sb = sb_new(NULL); - char first = 0, stop = 0; - int level = 0, d = 0; - while (1) { - d = fgetc(f); - if (d == EOF) { - if (first) - die("Invalid json-data from stdin"); - else - recorder_exit(EXIT_SUCCESS); - } - if (first == 0) { - if (d == '{') - stop = '}'; - else if (d == '[') - stop = ']'; - else - continue; - first = d; - } - - sb_add_char(sb, (char) d); - if (d == first) level++; - if (d == stop) level--; - if (level == 0) { - // time to execute - in3_req_t* ctx = req_new(c, sb->data); - if (ctx->error) - recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":{\"code\":%i,\"message\":\"%s\"}\n", 1, ctx->verification_state, ctx->error); - else { - in3_ret_t ret = in3_send_req(ctx); - uint32_t id = d_get_int(ctx->requests[0], K_ID); - if (ctx->error) { - for (char* x = ctx->error; *x; x++) { - if (*x == '\n') *x = ' '; - } - } - - if (ret == IN3_OK) { - if (c->flags & FLAGS_KEEP_IN3) { - str_range_t rr = d_to_json(ctx->responses[0]); - rr.data[rr.len] = 0; - recorder_print(0, "%s\n", rr.data); - } - else { - d_token_t* result = d_get(ctx->responses[0], K_RESULT); - d_token_t* error = d_get(ctx->responses[0], K_ERROR); - char* r = d_create_json(ctx->response_context, result ? result : error); - if (result) - recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"result\":%s}\n", id, r); - else - recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":%s}\n", id, r); - _free(r); - } - } - else - recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":{\"code\":%i,\"message\":\"%s\"}}\n", id, ctx->verification_state, ctx->error == NULL ? "Unknown error" : ctx->error); - } - req_free(ctx); - first = 0; - sb->len = 0; - } - } -} - -char* resolve(in3_t* c, char* name) { - if (!name) return NULL; - if (name[0] == '0' && name[1] == 'x') return name; - if (strstr(name, ".eth")) { - char* params = alloca(strlen(name) + 10); - sprintf(params, "[\"%s\"]", name); - char *res = NULL, *err = NULL; - in3_client_rpc(c, "in3_ens", params, &res, &err); - if (err) { - res = alloca(strlen(err) + 100); - sprintf(res, "Could not resolve %s : %s", name, err); - die(res); - } - if (res[0] == '"') { - res[strlen(res) - 1] = 0; - res++; - } - return res; - } - return name; -} - -// read data from a file and return the bytes -bytes_t readFile(FILE* f) { - if (!f) die("Could not read the input file"); - size_t allocated = 1024, len = 0, r; - uint8_t* buffer = _malloc(1025); - while (1) { - r = fread(buffer + len, 1, allocated - len, f); - len += r; - if (feof(f)) break; - size_t new_alloc = allocated * 2 + 1; - buffer = _realloc(buffer, new_alloc, allocated); - allocated = new_alloc; - } - buffer[len] = 0; - return bytes(buffer, len); -} - -// read from stdin and try to optimize hexdata. -bytes_t* get_std_in() { - if (feof(stdin)) return NULL; - bytes_t content = readFile(stdin); - - // this check tries to discover a solidity compilation poutput - char* bin = strstr((char*) content.data, "\nBinary: \n"); - if (bin) { - bin += 10; - char* end = strstr(bin, "\n"); - if (end) - return hex_to_new_bytes(bin, end - bin); - } - - // is it content starting with 0x, we treat it as hex otherwisae as rwa string - bytes_t* res = (content.len > 1 && *content.data == '0' && content.data[1] == 'x') - ? hex_to_new_bytes((char*) content.data + 2, content.len - 2) - : hex_to_new_bytes((char*) content.data, content.len); - _free(content.data); - return res; -} - -// convert the name to a chain_id -uint64_t getchain_id(char* name) { - if (strcmp(name, "mainnet") == 0) return CHAIN_ID_MAINNET; - if (strcmp(name, "goerli") == 0) return CHAIN_ID_GOERLI; - if (strcmp(name, "ewc") == 0) return CHAIN_ID_EWC; - if (strcmp(name, "ipfs") == 0) return CHAIN_ID_IPFS; - if (strcmp(name, "btc") == 0) return CHAIN_ID_BTC; - if (strcmp(name, "local") == 0) return CHAIN_ID_LOCAL; - if (name[0] == '0' && name[1] == 'x') { - bytes32_t d; - return bytes_to_long(d, hex_to_bytes(name + 2, -1, d, 32)); - } - die("Unknown or unsupported chain"); - return 0; -} - -// set the chain_id in the client -void set_chain_id(in3_t* c, char* id) { - c->chain.chain_id = strstr(id, "://") ? CHAIN_ID_LOCAL : getchain_id(id); - if (c->chain.chain_id == CHAIN_ID_LOCAL) { - sb_t* sb = sb_new("{\"autoUpdateList\":false,\"proof\":\"none\""); - sb_add_chars(sb, ",\"nodeRegistry\":{\"needsUpdate\":false,\"nodeList\":["); - sb_add_chars(sb, "{\"address\":\"0x0000000000000000000000000000000000000000\""); - sb_add_chars(sb, ",\"url\":\""); - sb_add_chars(sb, strstr(id, "://") ? id : "http://localhost:8545"); - sb_add_chars(sb, "\",\"props\":\"0xffff\"}"); - sb_add_chars(sb, "]}}}"); - char* err = in3_configure(c, sb->data); - if (err) - die(err); - sb_free(sb); - } -} - -// prepare a eth_call or eth_sendTransaction -abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_number, uint64_t gas, uint64_t gas_price, char* value, bytes_t* data, char* from) { - char* error = NULL; - bytes_t rdata = {0}; - abi_sig_t* req = fn_sig ? abi_sig_create(fn_sig, &error) : NULL; // only if we have a function signature, we will parse it and create a call_request. - if (error) die(error); // parse-error we stop here. - if (req) { // if type is a tuple, it means we have areuments we need to parse. - json_ctx_t* in_data = parse_json(args->data); // the args are passed as a "[]"- json-array string. - rdata = abi_encode(req, in_data->result, &error); //encode data - if (error) die(error); // we then set the data, which appends the arguments to the functionhash. - json_free(in_data); // of course we clean up ;-) - } // - sb_t* params = sb_new("[{"); // now we create the transactionobject as json-argument. - if (to) { // if this is a deployment we must not include the to-property - sb_add_chars(params, "\"to\":\""); - sb_add_chars(params, to); - sb_add_chars(params, "\" "); - } - if (req || data) { // if we have a request context or explicitly data we create the data-property - if (params->len > 2) sb_add_char(params, ','); // add comma if this is not the first argument - sb_add_chars(params, "\"data\":"); // we will have a data-property - if (req && data) { // if we have a both, we need to concat thewm (this is the case when depkloying a contract with constructorarguments) - uint8_t* full = _malloc(rdata.len - 4 + data->len); // in this case we skip the functionsignature. - memcpy(full, data->data, data->len); - memcpy(full + data->len, rdata.data + 4, rdata.len - 4); - bytes_t bb = bytes(full, rdata.len - 4 + data->len); - sb_add_bytes(params, "", &bb, 1, false); - _free(full); - } - else if (req) - sb_add_bytes(params, "", &rdata, 1, false); - else if (data) - sb_add_bytes(params, "", data, 1, false); - } - - if (block_number) { - sb_add_chars(params, "},\""); - sb_add_chars(params, block_number); - sb_add_chars(params, "\"]"); - } - else { - uint8_t gasdata[8]; - bytes_t g_bytes = bytes(gasdata, 8); - - if (value) { - sb_add_chars(params, ", \"value\":\""); - sb_add_chars(params, value); - sb_add_chars(params, "\""); - } - if (from) { - sb_add_chars(params, ", \"from\":\""); - sb_add_chars(params, from); - sb_add_chars(params, "\""); - } - - if (gas_price) { - long_to_bytes(gas_price, gasdata); - b_optimize_len(&g_bytes); - sb_add_bytes(params, ", \"gasPrice\":", &g_bytes, 1, false); - } - long_to_bytes(gas ? gas : 100000, gasdata); - g_bytes = bytes(gasdata, 8); - b_optimize_len(&g_bytes); - sb_add_bytes(params, ", \"gasLimit\":", &g_bytes, 1, false); - sb_add_chars(params, "}]"); - } - args->len = 0; - sb_add_chars(args, params->data); - sb_free(params); - return req; -} - -void print_val(d_token_t* t) { - switch (d_type(t)) { - case T_ARRAY: - case T_OBJECT: { - char* level = d_get_string(t, key("level")); - if (level) { - char* msg = d_get_string(t, key("msg")); - if (strcmp(level, "main") == 0) recorder_print(0, COLOR_GREEN_STR "\n", msg); - if (strcmp(level, "info") == 0) recorder_print(0, "%s\n", msg); - if (strcmp(level, "warning") == 0) recorder_print(0, COLOR_YELLOW_STR "\n", msg); - if (strcmp(level, "error") == 0) recorder_print(0, COLOR_RED_STR "\n", msg); - } - else { - for (d_iterator_t it = d_iter(t); it.left; d_iter_next(&it)) - print_val(it.token); - } - } break; - case T_BOOLEAN: - recorder_print(0, "%s\n", d_int(t) ? "true" : "false"); - break; - case T_INTEGER: - recorder_print(0, "%i\n", d_int(t)); - break; - case T_BYTES: - if (t->len < 9) - recorder_print(0, "%" PRId64 "\n", d_long(t)); - else { - recorder_print(0, "0x"); - for (int i = 0; i < (int) t->len; i++) recorder_print(0, "%02x", t->data[i]); - recorder_print(0, "\n"); - } - break; - case T_NULL: - recorder_print(0, "NULL\n"); - break; - case T_STRING: - recorder_print(0, "%s\n", d_string(t)); - break; - } -} -// decode pk -void read_pk(char* pk_file, char* pwd, in3_t* c, char* method) { - if (pk_file) { - if (!pwd) { - recorder_print(1, "Passphrase:\n"); - pwd = malloc(500); - read_pass(pwd, 500); - } - char* content; - if (strcmp(pk_file, "-") == 0) - content = (char*) readFile(stdin).data; - else if (pk_file[0] == '{') - content = pk_file; - else - content = (char*) readFile(fopen(pk_file, "r")).data; - - json_ctx_t* key_json = parse_json(content); - if (!key_json) die("invalid json in pk file"); - - uint8_t* pk_seed = malloc(32); - if (decrypt_key(key_json->result, pwd, pk_seed)) die("Invalid key"); - - if (!method || strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0) { - char tmp[64]; - bytes_to_hex(pk_seed, 32, tmp); - recorder_print(0, "0x%s\n", tmp); - recorder_exit(0); - } - else - eth_set_pk_signer(c, pk_seed); - } -} -#ifdef NODESELECT_DEF -static void set_nodelist(in3_t* c, char* nodes, bool update) { - if (!update) c->flags = FLAGS_STATS | FLAGS_BOOT_WEIGHTS | (c->flags & FLAGS_ALLOW_EXPERIMENTAL); - char* cpy = alloca(strlen(nodes) + 1); - in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); - if (!update && nl->nodelist_upd8_params) { - _free(nl->nodelist_upd8_params); - nl->nodelist_upd8_params = NULL; - } - memcpy(cpy, nodes, strlen(nodes) + 1); - char* s = NULL; - sb_t* sb = sb_new("{\"nodeRegistry\":{\"needsUpdate\":false,\"nodeList\":["); - for (char* next = strtok(cpy, ","); next; next = strtok(NULL, ",")) { - if (next != cpy) sb_add_char(sb, ','); - str_range_t address, url; - - if (*next == '0' && next[1] == 'x' && (s = strchr(next, ':'))) { - address = (str_range_t){.data = next, .len = s - next}; - url = (str_range_t){.data = s + 1, .len = strlen(s + 1)}; - } - else { - address = (str_range_t){.data = "0x1234567890123456789012345678901234567890", .len = 42}; - url = (str_range_t){.data = next, .len = strlen(next)}; - } - sb_add_chars(sb, "{\"address\":\""); - sb_add_range(sb, address.data, 0, address.len); - sb_add_chars(sb, "\",\"url\":\""); - sb_add_range(sb, url.data, 0, url.len); - sb_add_chars(sb, "\",\"props\":\"0xffff\"}"); - } - sb_add_chars(sb, "]}}}"); - char* err = in3_configure(c, sb->data); - if (err) - die(err); - sb_free(sb); -} -#endif -static bytes_t* last_response; -static bytes_t in_response = {.data = NULL, .len = 0}; -static bool only_show_raw_tx = false; -static in3_ret_t debug_transport(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx) { - UNUSED_VAR(plugin_data); - - in3_http_request_t* req = plugin_ctx; - if (action == PLGN_ACT_TRANSPORT_SEND) { -#ifndef DEBUG - if (debug_mode) - fprintf(stderr, "send request to %s: \n" COLORT_RYELLOW "%s" COLORT_RESET "\n", req->urls_len ? req->urls[0] : "none", req->payload); -#endif - if (in_response.len) { - for (unsigned int i = 0; i < req->urls_len; i++) { - req->req->raw_response[i].state = IN3_OK; - sb_add_range(&req->req->raw_response[i].data, (char*) in_response.data, 0, in_response.len); - req->req->raw_response[i].state = IN3_OK; - } - return 0; - } - if (only_show_raw_tx && str_find(req->payload, "\"method\":\"eth_sendRawTransaction\"")) { - char* data = str_find(req->payload, "0x"); - *strchr(data, '"') = 0; - recorder_print(0, "%s\n", data); - recorder_exit(EXIT_SUCCESS); - } - } -#ifdef USE_CURL - in3_ret_t r = send_curl(NULL, action, plugin_ctx); -#elif USE_WINHTTP - in3_ret_t r = send_winhttp(NULL, action, plugin_ctx); -#elif TRANSPORTS - in3_ret_t r = send_http(NULL, action, plugin_ctx); -#else - in3_ret_t r = req_set_error(req->req, "No transport supported in the client", IN3_ECONFIG); -#endif - if (action != PLGN_ACT_TRANSPORT_CLEAN) { - last_response = b_new((uint8_t*) req->req->raw_response[0].data.data, req->req->raw_response[0].data.len); -#ifndef DEBUG - if (debug_mode) { - if (req->req->raw_response[0].state == IN3_OK) - fprintf(stderr, "success response \n" COLORT_RGREEN "%s" COLORT_RESET "\n", req->req->raw_response[0].data.data); - else - fprintf(stderr, "error response \n" COLORT_RRED "%s" COLORT_RESET "\n", req->req->raw_response[0].data.data); - } -#endif - } - return r; -} -static char* test_name = NULL; -static in3_ret_t test_transport(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx) { - UNUSED_VAR(plugin_data); - in3_http_request_t* req = plugin_ctx; -#ifdef USE_CURL - in3_ret_t r = send_curl(NULL, action, plugin_ctx); -#elif USE_WINHTTP - in3_ret_t r = send_winhttp(NULL, action, plugin_ctx); -#elif TRANSPORTS - in3_ret_t r = send_http(NULL, action, plugin_ctx); -#else - in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; -#endif - if (r == IN3_OK) { - req->payload[strlen(req->payload) - 1] = 0; - recorder_print(0, "[{ \"descr\": \"%s\",\"chainId\": \"0x1\", \"verification\": \"proof\",\"binaryFormat\": false, \"request\": %s, \"response\": %s }]", test_name, req->payload + 1, req->req->raw_response->data.data); - recorder_exit(0); - } - - return r; -} - -int main(int argc, char* argv[]) { - // check for usage - bool use_pk = false; - if (argc >= 2 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) { - show_help(argv[0]); - recorder_exit(0); - } - - if (argc >= 2 && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-version") == 0)) { - recorder_print(0, "in3 " IN3_VERSION "\nbuild " __DATE__ " with"); -#ifdef TEST - recorder_print(0, " -DTEST=true"); -#endif -#ifdef EVM_GAS - recorder_print(0, " -DEVM_GAS=true"); -#endif -#ifdef CMD - recorder_print(0, " -DCMD=true"); -#endif -#ifdef IN3_MATH_FAST - recorder_print(0, " -DFAST_MATH=true"); -#endif -#ifdef IN3_SERVER - recorder_print(0, " -DIN3_SERVER=true"); -#endif -#ifdef USE_CURL - recorder_print(0, " -DUSE_CURL=true"); -#else - recorder_print(0, " -DUSE_CURL=false"); -#endif - recorder_print(0, "\n(c) " IN3_COPYRIGHT "\n"); - recorder_exit(0); - } - - // define vars - char* method = NULL; - sb_t* args = sb_new("["); - int i; -#ifdef LEDGER_NANO - uint8_t path[5]; -#endif - - // we want to verify all - in3_log_set_level(LOG_INFO); - - // create the client - in3_t* c = in3_for_chain(CHAIN_ID_MAINNET); - bool out_response = false; - int run_test_request = 0; - bool force_hex = false; - char* sig = NULL; - char* to = NULL; - char* block_number = "latest"; - char* name = NULL; - abi_sig_t* req = NULL; - bool json = false; - char* ms_sigs = NULL; - char* allowed_methods = NULL; - uint64_t gas_limit = 100000; - uint64_t gas_price = 0; - char* value = NULL; - bool wait = false; - char* pwd = NULL; - char* pk_file = NULL; - char* validators = NULL; - bytes_t* data = NULL; - char* port = NULL; - char* sig_type = "raw"; - bool to_eth = false; - char* rc = "2"; - bool human_readable = false; - char* from = NULL; - - in3_plugin_register(c, PLGN_ACT_TRANSPORT, debug_transport, NULL, true); +#include "handlers.h" +#include "helper.h" +#include "req_exec.h" +#include "transport.h" +#include "tx.h" -#ifdef USE_WINHTTP - rc = "1"; -#endif - -#ifdef NODESELECT_DEF - _configure(c, "requestCount", "%s", rc); -#endif - - // handle clear cache opt before initializing cache - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-fi") == 0) { - recorder_update_cmd(argv[i + 1], &argc, &argv); - break; - } - if (strcmp(argv[i], "-pk") == 0) use_pk = true; - } - - // handle clear cache opt before initializing cache - for (i = 1; i < argc; i++) - if (strcmp(argv[i], "-ccache") == 0) - storage_clear(NULL); - - // use the storagehandler to cache data in .in3 - in3_register_file_storage(c); - - // check env - if (getenv("IN3_PK") && !use_pk) { - char* pks = _strdupn(getenv("IN3_PK"), -1); - bytes32_t pk; - for (char* cc = strtok(pks, ","); cc; cc = strtok(NULL, ",")) { - hex_to_bytes(cc, -1, pk, 32); - eth_set_pk_signer(c, pk); - } - } - -#ifdef ZKSYNC - if (getenv("IN3_ZKS")) configure_2("zksync", "provider_url", getenv("IN3_ZKS")); -#endif - - if (getenv("IN3_CHAIN")) - set_chain_id(c, getenv("IN3_CHAIN")); - - // fill from args - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-pk") == 0) { // private key? - if (argv[i + 1][0] == '0' && argv[i + 1][1] == 'x') { - bytes32_t pk; - hex_to_bytes(argv[++i], -1, pk, 32); - eth_set_pk_signer(c, pk); - } - else - pk_file = argv[++i]; - } - else if (strcmp(argv[i], "-path") == 0) { -#if defined(LEDGER_NANO) - if (argv[i + 1][0] == '0' && argv[i + 1][1] == 'x') { - hex_to_bytes(argv[++i], -1, path, 5); - eth_ledger_set_signer_txn(c, path); - } -#else - die("path option not supported currently "); -#endif - } - else if (strcmp(argv[i], "-chain") == 0 || strcmp(argv[i], "-c") == 0) // chain_id - set_chain_id(c, argv[++i]); - else if (strcmp(argv[i], "-ccache") == 0) // NOOP - should have been handled earlier - ; - else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-data") == 0) { // data - char* d = argv[++i]; - if (strcmp(d, "-") == 0) - data = get_std_in(); - else if (*d == '0' && d[1] == 'x') - data = hex_to_new_bytes(d + 2, strlen(d) - 2); - else { - FILE* f = fopen(d, "r"); - bytes_t content = readFile(f); - data = hex_to_new_bytes((char*) content.data + 2, content.len - 2); - fclose(f); - } - } - else if (strcmp(argv[i], "-block") == 0 || strcmp(argv[i], "-b") == 0) - block_number = argv[++i]; - else if (strcmp(argv[i], "-latest") == 0 || strcmp(argv[i], "-l") == 0) - c->replace_latest_block = atoll(argv[++i]); -#ifdef ZKSYNC - else if (strcmp(argv[i], "-zks") == 0) - configure_2("zksync", "provider_url", argv[++i]); - else if (strcmp(argv[i], "-zka") == 0) - configure_2("zksync", "account", argv[++i]); - else if (strcmp(argv[i], "-zcpm") == 0) - configure_2("zksync", "create_proof_method", argv[++i]); - else if (strcmp(argv[i], "-zvpm") == 0) - configure_2("zksync", "verify_proof_method", argv[++i]); - else if (strcmp(argv[i], "-zkat") == 0) - configure_2("zksync", "signer_type", argv[++i]); - else if (strcmp(argv[i], "-zms") == 0) - configure_2("zksync", "musig_pub_keys", argv[++i]); - else if (strcmp(argv[i], "-zmu") == 0) - _configure2(c, "zksync", "musig_urls", "[null,\"%s\"]", argv[++i]); - else if (strcmp(argv[i], "-zsk") == 0) - configure_2("zksync", "sync_key", argv[++i]); - else if (strcmp(argv[i], "-zc2") == 0) { - char* c2val = argv[++i]; - if (strlen(c2val) != 176) die("create2-arguments must have the form -zc2 ::"); - char tmp[177], t2[500]; - memcpy(tmp, c2val, 177); - tmp[42] = tmp[109] = 0; - sprintf(t2, "{\"zksync\":{\"signer_type\":\"create2\",\"create2\":{\"creator\":\"%s\",\"codehash\":\"%s\",\"saltarg\":\"%s\"}}}", tmp, tmp + 43, tmp + 110); - char* err = in3_configure(c, t2); - if (err) die(err); - } -#endif - else if (strcmp(argv[i], "-tr") == 0) - run_test_request = 1; - else if (strcmp(argv[i], "-thr") == 0) - run_test_request = 2; - // else if (strcmp(argv[i], "-x") == 0) - // c->flags |= FLAGS_ALLOW_EXPERIMENTAL; - else if (strcmp(argv[i], "-fo") == 0) - recorder_write_start(c, argv[++i], argc, argv); - else if (strcmp(argv[i], "-fi") == 0) - recorder_read_start(c, argv[++i]); - else if (strcmp(argv[i], "-h") == 0) - human_readable = true; -#ifdef NODESELECT_DEF - else if (strcmp(argv[i], "-nl") == 0) - set_nodelist(c, argv[++i], false); - else if (strcmp(argv[i], "-bn") == 0) - set_nodelist(c, argv[++i], true); -#endif - else if (strcmp(argv[i], "-mss") == 0 || strcmp(argv[i], "-sigs") == 0) - ms_sigs = argv[++i]; - else if (strcmp(argv[i], "-ms") == 0) { -#ifdef MULTISIG - address_t adr; - if (hex_to_bytes(argv[++i], -1, adr, 20) != 20) die("-ms must be exactly 20 bytes"); - add_gnosis_safe(c, adr); -#else - die("-ms is not supported. Compile with -DMULTISIG=true"); -#endif - } - else if (strcmp(argv[i], "-eth") == 0) - to_eth = true; - else if (strcmp(argv[i], "-md") == 0) - _configure(c, "minDeposit", "%s", argv[++i]); - else if (strcmp(argv[i], "-kin3") == 0) - c->flags |= FLAGS_KEEP_IN3; - else if (strcmp(argv[i], "-bw") == 0) - c->flags |= FLAGS_BOOT_WEIGHTS; - else if (strcmp(argv[i], "-to") == 0) - to = argv[++i]; - else if (strcmp(argv[i], "-gas") == 0 || strcmp(argv[i], "-gas_limit") == 0) - gas_limit = atoll(argv[++i]); - else if (strcmp(argv[i], "-gp") == 0 || strcmp(argv[i], "-gas_price") == 0) - gas_price = atoll(argv[++i]); - else if (strcmp(argv[i], "-test") == 0) { - test_name = argv[++i]; - in3_plugin_register(c, PLGN_ACT_TRANSPORT, test_transport, NULL, true); - } - else if (strcmp(argv[i], "-pwd") == 0) - pwd = argv[++i]; - else if (strcmp(argv[i], "-q") == 0) - in3_log_set_level(LOG_FATAL); - else if (strcmp(argv[i], "-value") == 0) - value = get_wei(argv[++i]); - else if (strcmp(argv[i], "-port") == 0) - port = argv[++i]; - else if (strcmp(argv[i], "-from") == 0) - from = argv[++i]; - else if (strcmp(argv[i], "-am") == 0) - allowed_methods = argv[++i]; - else if (strcmp(argv[i], "-os") == 0) - only_show_raw_tx = true; - else if (strcmp(argv[i], "-rc") == 0) - _configure(c, "requestCount", "%s", argv[++i]); - else if (strcmp(argv[i], "-a") == 0) - c->max_attempts = atoi(argv[++i]); - else if (strcmp(argv[i], "-name") == 0) - name = argv[++i]; - else if (strcmp(argv[i], "-validators") == 0) - validators = argv[++i]; - else if (strcmp(argv[i], "-hex") == 0) - force_hex = true; - else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-finality") == 0) - c->finality = (uint16_t) atoi(argv[++i]); - else if (strcmp(argv[i], "-response-out") == 0 || strcmp(argv[i], "-ro") == 0) - out_response = true; - else if (strcmp(argv[i], "-response-in") == 0 || strcmp(argv[i], "-ri") == 0) - in_response = readFile(stdin); - else if (strcmp(argv[i], "-wait") == 0 || strcmp(argv[i], "-w") == 0) - wait = true; - else if (strcmp(argv[i], "-json") == 0) - json = true; - else if (strcmp(argv[i], "-k") == 0) { - if (argc <= i + 1 || strlen(argv[i + 1]) > 66) die("Invalid signer key"); - bytes32_t k; - hex_to_bytes(argv[++i], -1, k, 32); - eth_set_request_signer(c, k); - } - else if (strcmp(argv[i], "-np") == 0) - c->proof = PROOF_NONE; - else if (strcmp(argv[i], "-ns") == 0) - c->flags ^= FLAGS_STATS; - else if (strcmp(argv[i], "-sigtype") == 0 || strcmp(argv[i], "-st") == 0) - sig_type = argv[++i]; - else if (strcmp(argv[i], "-debug") == 0) { - in3_log_set_quiet(false); - in3_log_set_level(LOG_TRACE); - debug_mode = true; - } - else if (strcmp(argv[i], "-signs") == 0 || strcmp(argv[i], "-s") == 0) - c->signature_count = atoi(argv[++i]); - else if (strcmp(argv[i], "-proof") == 0 || strcmp(argv[i], "-p") == 0) { - if (strcmp(argv[i + 1], "none") == 0) - c->proof = PROOF_NONE; - else if (strcmp(argv[i + 1], "standard") == 0) - c->proof = PROOF_STANDARD; - else if (strcmp(argv[i + 1], "full") == 0) - c->proof = PROOF_FULL; - else - die("Invalid Argument for proof, must be none, standard or full"); - i++; - } - // now handle arguments for special methods - else if (configure_arg(c, argv, &i, argc)) - continue; - else { - if (method == NULL) - method = argv[i]; - else if (strcmp(method, "keystore") == 0 || strcmp(method, "key") == 0) - pk_file = argv[i]; - else if (strcmp(method, "sign") == 0 && !data) - data = b_new((uint8_t*) argv[i], strlen(argv[i])); - else if (sig == NULL && (strcmp(method, "call") == 0 || strcmp(method, "send") == 0 || strcmp(method, "abi_encode") == 0 || strcmp(method, "abi_decode") == 0)) - sig = argv[i]; - else { - // otherwise we add it to the params - if (args->len > 1) sb_add_char(args, ','); - if (*argv[i] >= '0' && *argv[i] <= '9' && *(argv[i] + 1) != 'x' && strcmp(method, "in3_toWei") && c->chain.chain_id != CHAIN_ID_BTC) - sb_print(args, "\"%s\"", get_wei(argv[i])); - else - sb_print(args, - (argv[i][0] == '{' || argv[i][0] == '[' || strcmp(argv[i], "true") == 0 || strcmp(argv[i], "false") == 0 || (*argv[i] >= '0' && *argv[i] <= '9' && strlen(argv[i]) < 16 && *(argv[i] + 1) != 'x')) - ? "%s" - : "\"%s\"", - strcmp(method, "in3_ens") ? resolve(c, argv[i]) : argv[i]); - } - } - } - sb_add_char(args, ']'); - char *result = NULL, *error = NULL; - -#ifdef IN3_SERVER - // start server - if (!method && port) { - http_run_server(port, c, allowed_methods); - recorder_exit(0); - } -#else - (void) (port); - (void) (allowed_methods); -#endif - - // handle private key - if (pk_file) read_pk(pk_file, pwd, c, method); - - // no proof for rpc-chain - if (c->chain.chain_id == 0xFFFF) c->proof = PROOF_NONE; - - // make sure boot nodes are initialized - char buf[15 + 11 /* UINT32_MAX */]; - sprintf(buf, "{\"chainId\":%" PRIu32 "}", c->chain.chain_id); - in3_configure(c, buf); - - // execute the method - if (sig && *sig == '-') die("unknown option"); - if (!method) { - in3_log_info("in3 " IN3_VERSION " - reading json-rpc from stdin. (exit with ctrl C)\n________________________________________________\n"); - execute(c, stdin); - recorder_exit(0); - } - if (*method == '-') die("unknown option"); - - // call -> eth_call - if (strcmp(method, "call") == 0) { - req = prepare_tx(sig, resolve(c, to), args, block_number, 0, 0, NULL, data, from); - method = "eth_call"; - } - else if (strcmp(method, "abi_encode") == 0) { - char* error = NULL; - json_ctx_t* in_data = parse_json(args->data); - if (!in_data) die("iinvalid params"); - if (!sig) die("missing signature"); - abi_sig_t* s = abi_sig_create(sig, &error); - if (s && !error) { - bytes_t data = abi_encode(s, in_data->result, &error); - if (data.data) - print_hex(data.data, data.len); - } - if (error) die(error); - recorder_exit(0); - } - else if (strcmp(method, "abi_decode") == 0) { - char* error = NULL; - json_ctx_t* in_data = parse_json(args->data); - if (!in_data) die("invalid params"); - if (!sig) die("missing signature"); - abi_sig_t* s = abi_sig_create(sig, &error); - if (s && !error) { - bytes_t data = d_to_bytes(d_get_at(parse_json(args->data)->result, 0)); - json_ctx_t* res = abi_decode(s, data, &error); - if (error) die(error); - if (json) - recorder_print(0, "%s\n", d_create_json(res, res->result)); - else - print_val(res->result); - } - if (error) die(error); - recorder_exit(0); -#ifdef IPFS - } - else if (strcmp(method, "ipfs_get") == 0) { - c->chain.chain_id = CHAIN_ID_IPFS; - int size = args->len; - if (size == 2 || args->data[1] != '"' || size < 20 || strstr(args->data + 2, "\"") == NULL) die("missing ipfs hash"); - args->data[size - 2] = 0; - bytes_t* content = ipfs_get(c, args->data + 2); - if (!content) die("IPFS hash not found!"); - fwrite(content->data, content->len, 1, stdout); - fflush(stdout); - recorder_exit(0); - } - else if (strcmp(method, "ipfs_put") == 0) { - c->chain.chain_id = CHAIN_ID_IPFS; - bytes_t data = readFile(stdin); - data.data[data.len] = 0; - recorder_print(0, "%s\n", ipfs_put(c, &data)); - recorder_exit(0); - -#endif - } -#ifdef NODESELECT_DEF - else if (strcmp(method, "in3_weights") == 0) { - c->max_attempts = 1; - uint32_t block = 0, b = 0; - BIT_CLEAR(c->flags, FLAGS_AUTO_UPDATE_LIST); - uint64_t now = in3_time(NULL); - char* more = "WEIGHT"; - in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); - in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); - if (run_test_request == 1) more = "WEIGHT : LAST_BLOCK"; - if (run_test_request == 2) more = "WEIGHT : NAME VERSION : RUNNING : HEALTH : LAST_BLOCK"; - recorder_print(0, " : %-45s : %7s : %5s : %5s: %s\n------------------------------------------------------------------------------------------------\n", "URL", "BL", "CNT", "AVG", more); - for (unsigned int i = 0; i < nl->nodelist_length; i++) { - in3_req_t* ctx = NULL; - char* health_s = NULL; - if (run_test_request) { - char req[300]; - char adr[41]; - bytes_to_hex((nl->nodelist + i)->address, 20, adr); - sprintf(req, "{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"in3\":{\"dataNodes\":[\"0x%s\"]}}", adr); - ctx = req_new(c, req); - if (ctx) in3_send_req(ctx); - if (run_test_request == 2) { - int health = 1; - char* version = ""; - char* node_name = ""; - uint32_t running = 0; - json_ctx_t* health_res = NULL; - char health_url[500]; - char* urls[1]; - urls[0] = health_url; - sprintf(health_url, "%s/health", nl->nodelist[i].url); - in3_http_request_t r = {0}; - in3_req_t ctx = {0}; - ctx.raw_response = _calloc(sizeof(in3_response_t), 1); - ctx.raw_response->state = IN3_WAITING; - ctx.client = c; - r.req = &ctx; - r.urls = urls; - r.urls_len = 1; - r.payload = ""; -#ifdef USE_CURL - send_curl(NULL, PLGN_ACT_TRANSPORT_SEND, &r); -#elif USE_WINHTTP - send_winhttp(NULL, PLGN_ACT_TRANSPORT_SEND, &r); -#elif TRANSPORTS - send_http(NULL, PLGN_ACT_TRANSPORT_SEND, &r); -#endif - if (ctx.raw_response->state) - health = 0; - else { - health_res = parse_json(ctx.raw_response->data.data); - if (!health_res) - health = 0; - else { - node_name = d_get_string(health_res->result, key("name")); - version = d_get_string(health_res->result, key("version")); - running = d_get_int(health_res->result, key("running")); - char* status = d_get_string(health_res->result, key("status")); - if (!status || strcmp(status, "healthy")) health = 0; - } - } - if (version) { - char* l = strrchr(version, ':'); - if (l) version = l + 1; - } - health_s = _malloc(3000); - sprintf(health_s, "%-22s %-7s %7d %-9s ", node_name ? node_name : "-", version ? version : "-", running, health ? "OK" : "unhealthy"); - - if (ctx.raw_response->data.data) - _free(ctx.raw_response->data.data); - _free(ctx.raw_response); - if (health_res) json_free(health_res); - } - } - in3_node_t* node = nl->nodelist + i; - in3_node_weight_t* weight = nl->weights + i; - uint64_t blacklisted = weight->blacklisted_until > now ? weight->blacklisted_until : 0; - uint32_t calc_weight = in3_node_calculate_weight(weight, node->capacity, now); - char * tr = NULL, *warning = NULL; - if (ctx) { - tr = _malloc(1000); - if (!ctx->error && d_get(ctx->responses[0], K_ERROR)) { - d_token_t* msg = d_get(ctx->responses[0], K_ERROR); - if (d_type(msg) == T_OBJECT) msg = d_get(msg, K_MESSAGE); - sprintf((warning = tr), "%s", msg ? d_string(msg) : "Error-Response!"); - } - else if (!ctx->error) { - b = d_get_int(ctx->responses[0], K_RESULT); - if (block < b) block = b; - - if (b < block - 1) - sprintf((warning = tr), "#%i ( out of sync : %i blocks behind latest )", b, block - b); - else if (strncmp(node->url, "https://", 8)) - sprintf((warning = tr), "#%i (missing https, which is required in a browser )", b); - else if (!IS_APPROX(d_get_int(ctx->responses[0], K_RESULT), d_get_int(d_get(ctx->responses[0], K_IN3), K_CURRENT_BLOCK), 1)) - sprintf((warning = tr), "#%i ( current block mismatch: %i blocks apart )", b, - d_get_int(ctx->responses[0], K_RESULT) - d_get_int(d_get(ctx->responses[0], K_IN3), K_CURRENT_BLOCK)); - else - sprintf(tr, "#%i", b); - } - else if (!strlen(node->url) || !node->props) - sprintf((warning = tr), "No URL spcified anymore props = %i ", (int) (node->props & 0xFFFFFF)); - else if ((node->props & NODE_PROP_DATA) == 0) - sprintf((warning = tr), "The node is marked as not supporting Data-Providing"); - else if (c->proof != PROOF_NONE && (node->props & NODE_PROP_PROOF) == 0) - sprintf((warning = tr), "The node is marked as able to provide proof"); - else if ((c->flags & FLAGS_HTTP) && (node->props & NODE_PROP_HTTP) == 0) - sprintf((warning = tr), "The node is marked as able to support http-requests"); - else - tr = ctx->error; - if (strlen(tr) > 100) tr[100] = 0; - } - if (blacklisted) - recorder_print(0, COLORT_RED); - else if (warning) - recorder_print(0, COLORT_YELLOW); - else if (!weight->response_count) - recorder_print(0, COLORT_DARKGRAY); - else - recorder_print(0, COLORT_GREEN); - recorder_print(0, "%2i %-45s %7i %5i %5i %5i %s%s", i, node->url, (int) (blacklisted ? blacklisted - now : 0), weight->response_count, weight->response_count ? (weight->total_response_time / weight->response_count) : 0, calc_weight, health_s ? health_s : "", tr ? tr : ""); - recorder_print(0, COLORT_RESET "\n"); - if (tr && tr != ctx->error) _free(tr); - if (health_s) _free(health_s); - if (ctx) req_free(ctx); - } - - recorder_exit(0); - } -#endif - else if (strcmp(method, "send") == 0) { - prepare_tx(sig, resolve(c, to), args, NULL, gas_limit, gas_price, value, data, from); - if (only_show_raw_tx && (c->plugin_acts & (PLGN_ACT_SIGN | PLGN_ACT_SIGN_ACCOUNT)) == 0) - method = "in3_prepareTx"; - else - method = wait ? "eth_sendTransactionAndWait" : "eth_sendTransaction"; - } - else if (strcmp(method, "sign") == 0) { - if (!data) die("no data given"); - if (data->len > 2 && data->data[0] == '0' && data->data[1] == 'x') - data = hex_to_new_bytes((char*) data->data + 2, data->len - 2); - if (strcmp(sig_type, "eth_sign") == 0) { - char* tmp = alloca(data->len + 30); - int l = sprintf(tmp, "\x19" - "Ethereum Signed Message:\n%u", - data->len); - memcpy(tmp + l, data->data, data->len); - data = b_new((uint8_t*) tmp, l + data->len); - sig_type = "raw"; - } - - if (!in3_plugin_is_registered(c, PLGN_ACT_SIGN)) die("No private key/path given"); - in3_req_t ctx; - ctx.client = c; - in3_sign_ctx_t sc = {0}; - sc.req = &ctx; - sc.account = bytes(NULL, 0); - sc.message = *data; - sc.type = strcmp(sig_type, "hash") == 0 ? SIGN_EC_RAW : SIGN_EC_HASH; -#if defined(LEDGER_NANO) - if (c->signer->sign == eth_ledger_sign_txn) { // handling specific case when ledger nano signer is ethereum firmware app - char prefix[] = "msg"; - bytes_t* tmp_data = b_new((uint8_t*) NULL, data->len + strlen(prefix)); - uint8_t hash[32]; - - hasher_Raw(HASHER_SHA2, data->data, data->len, hash); - recorder_print(0, "Match the following hash with the message hash on ledger device\n"); - print_hex(hash, 32); - - memcpy(tmp_data->data, prefix, strlen(prefix)); - memcpy(tmp_data->data + strlen(prefix), data->data, data->len); - - sc.message = *tmp_data; - in3_plugin_execute_first(&ctx, PLGN_ACT_SIGN, &sc); - - b_free(tmp_data); - } - else { - in3_plugin_execute_first(&ctx, PLGN_ACT_SIGN, &sc); - } -#else - in3_plugin_execute_first(&ctx, PLGN_ACT_SIGN, &sc); -#endif - - if (sc.signature.len == 65) sc.signature.data[64] += 27; - print_hex(sc.signature.data, sc.signature.len); - recorder_exit(0); - } - else if (strcmp(method, "chainspec") == 0) { - char* json; - if (args->len > 2) { - args->data[args->len - 2] = 0; - json = (char*) readFile(fopen(args->data + 2, "r")).data; - } - else - json = (char*) readFile(stdin).data; - json_ctx_t* j = parse_json_indexed(json); - chainspec_t* spec = chainspec_create_from_json(j); - if (validators) { - // first PoA without validators-list - for (uint32_t i = 0; i < spec->consensus_transitions_len; i++) { - if (spec->consensus_transitions[i].validators.len == 0) { - spec->consensus_transitions[i].validators = *hex_to_new_bytes(validators + 2, strlen(validators) - 2); - break; - } - } - } - bytes_builder_t* bb = bb_new(); - chainspec_to_bin(spec, bb); - - if (force_hex) - print_hex(bb->b.data, bb->b.len); - else { - bool is_hex = false; - recorder_print(0, "#define CHAINSPEC_%s \"", name); - for (i = 0; i < (int) bb->b.len; i++) { - uint8_t c = bb->b.data[i]; - if (is_hex && ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) recorder_print(0, "\" \""); - is_hex = c < ' ' || c > 0x7E || c == 0x5C || c == '"'; - recorder_print(0, is_hex ? "\\x%02x" : "%c", c); - } - recorder_print(0, "\"\n"); - } - - recorder_exit(0); - } - else if (strcmp(method, "autocompletelist") == 0) { - recorder_print(0, "send call abi_encode abi_decode ipfs_get ipfs_put ecrecover key -sigtype -st eth_sign raw hash sign createkey -ri -ro keystore unlock pk2address pk2public mainnet goerli ewc btc ipfs local true false latest -np -debug -c -chain -p -version -proof -s -signs -b -block -to -d -data -gas_limit -value -w -wait -hex -json in3_nodeList in3_stats in3_sign web3_clientVersion web3_sha3 net_version net_peerCount net_listening eth_protocolVersion eth_syncing eth_coinbase eth_mining eth_hashrate eth_gasPrice eth_accounts eth_blockNumber eth_getBalance eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getCode eth_sign eth_sendTransaction eth_sendRawTransaction eth_call eth_estimateGas eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockHashAndIndex eth_getTransactionByBlockNumberAndIndex eth_getTransactionReceipt eth_pendingTransactions eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileLLL eth_compileSolidity eth_compileSerpent eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_getWork eth_submitWork eth_submitHashrate in3_cacheClear\n"); - recorder_exit(0); - } - else if (strcmp(method, "createkey") == 0) { - srand(current_ms() % 0xFFFFFFFF); - recorder_print(0, "0x"); - for (i = 0; i < 32; i++) recorder_print(0, "%02x", rand() % 256); - recorder_print(0, "\n"); - recorder_exit(0); - } - else if (strcmp(method, "pk2address") == 0) { - bytes32_t prv_key; - uint8_t public_key[65], sdata[32]; - hex_to_bytes(argv[argc - 1], -1, prv_key, 32); - ecdsa_get_public_key65(&secp256k1, prv_key, public_key); - keccak(bytes(public_key + 1, 64), sdata); - recorder_print(0, "0x"); - for (i = 0; i < 20; i++) recorder_print(0, "%02x", sdata[i + 12]); - recorder_print(0, "\n"); - recorder_exit(0); - } - else if (strcmp(method, "pk2public") == 0) { - bytes32_t prv_key; - uint8_t public_key[65]; - hex_to_bytes(argv[argc - 1], -1, prv_key, 32); - ecdsa_get_public_key65(&secp256k1, prv_key, public_key); - print_hex(public_key + 1, 64); - recorder_exit(0); - } - else if (strcmp(method, "ecrecover") == 0) { - json_ctx_t* rargs = parse_json(args->data); - if (!rargs || d_len(rargs->result) < 2) die("Invalid arguments for recovery args must be : "); - bytes_t msg = d_to_bytes(d_get_at(rargs->result, 0)); - bytes_t sig = d_to_bytes(d_get_at(rargs->result, 1)); - bytes32_t hash; - uint8_t pub[65]; - if (strcmp(sig_type, "eth_sign") == 0) { - char* tmp = alloca(msg.len + 30); - int l = sprintf(tmp, "\x19" - "Ethereum Signed Message:\n%u", - msg.len); - memcpy(tmp + l, msg.data, msg.len); - msg = *b_new((uint8_t*) tmp, l + msg.len); - } - if (strcmp(sig_type, "hash") == 0) { - if (msg.len != 32) die("The message hash must be 32 byte"); - memcpy(hash, msg.data, 32); - } - else - keccak(msg, hash); - if (sig.len != 65) die("The signature must be 65 bytes"); - - if (ecdsa_recover_pub_from_sig(&secp256k1, pub, sig.data, hash, sig.data[64] >= 27 ? sig.data[64] - 27 : sig.data[64])) - die("Invalid Signature"); - - keccak(bytes(pub + 1, 64), hash); - print_hex(hash + 12, 20); - print_hex(pub + 1, 64); - recorder_exit(0); - } - - in3_log_debug("..sending request %s %s\n", method, args->data); - - if (wait && strcmp(method, "eth_sendTransaction") == 0) method = "eth_sendTransactionAndWait"; - - // send the request +static void send_request(in3_t* c, int argc, char** argv, char* method, sb_t* args, char** result, char** error) { sb_t* sb = sb_new("{\"method\":\""); sb_add_chars(sb, method); sb_add_chars(sb, "\",\"params\":"); sb_add_chars(sb, args->data); + char* ms_sigs = get_argument(argc, argv, "-sigs", "--ms.signatures", true); if (ms_sigs) { sb_add_chars(sb, ",\"in3\":{\"msSigs\":\""); sb_add_chars(sb, ms_sigs); @@ -1368,9 +20,8 @@ int main(int argc, char* argv[]) { } else sb_add_chars(sb, "}"); - - in3_client_rpc_raw(c, sb->data, &result, &error); - + in3_client_rpc_raw(c, sb->data, result, error); + check_last_output(); #ifdef NODESELECT_DEF in3_chain_t* chain = &c->chain; in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); @@ -1379,65 +30,66 @@ int main(int argc, char* argv[]) { char *r = NULL, *e = NULL; if (chain->type == CHAIN_ETH) in3_client_rpc(c, "eth_blockNumber", "[]", &r, &e); - // else if (chain->type == CHAIN_BTC) - // in3_client_rpc(c, "getblockcount", "[]", &r, &e); } #endif +} - if (error) - die(error); - else if (!result) - die("No result"); - else { +int main(int argc, char* argv[]) { + // we want to verify all + in3_log_set_level(LOG_INFO); - if (out_response && last_response) { - char* r = alloca(last_response->len + 1); - memcpy(r, last_response->data, last_response->len); - r[last_response->len] = 0; - recorder_print(0, "%s\n", r); - recorder_exit(0); - } + // define vars + char* method = NULL; + sb_t* args = sb_new("["); + in3_t* c = in3_for_chain(CHAIN_ID_MAINNET); - // if the result is a string, we remove the quotes - if (!human_readable && result[0] == '"' && result[strlen(result) - 1] == '"') { - memmove(result, result + 1, strlen(result)); - result[strlen(result) - 1] = 0; - } + init_transport(c); + init_recorder(&argc, &argv); + init_env(c, argc, argv); - // if the request was a eth_call, we decode the result - if (req) { - int l = strlen(result) / 2 - 1; - if (l) { - char* error = NULL; - uint8_t* tmp = alloca(l + 1); - json_ctx_t* res = abi_decode(req, bytes(tmp, hex_to_bytes(result, -1, tmp, l + 1)), &error); - if (error) die(error); - if (json) - recorder_print(0, "%s\n", d_create_json(res, res->result)); - else - print_val(res->result); - } - // if not we simply print the result - } - else if (human_readable) { - json_ctx_t* jctx = parse_json(result); - if (jctx) - print_val(jctx->result); - else - recorder_print(0, "%s\n", result); - } - else if (only_show_raw_tx && strcmp(method, "in3_prepareTx") == 0 && from) - recorder_print(0, "%s %s\n", result, from); + // parse arguments + for (int i = 1; i < argc; i++) { + // is it a argument? + if (configure_arg(c, argv, &i, argc)) continue; + + // now handle arguments for special methods + if (method == NULL) + method = argv[i]; + else if (strcmp(method, "sign") == 0 && !get_txdata()->data) + get_txdata()->data = b_new((uint8_t*) argv[i], strlen(argv[i])); + else if (get_txdata()->sig == NULL && (strcmp(method, "call") == 0 || strcmp(method, "send") == 0 || strcmp(method, "abi_encode") == 0 || strcmp(method, "abi_decode") == 0)) + get_txdata()->sig = argv[i]; else { - if (to_eth && result[0] == '0' && result[1] == 'x' && strlen(result) <= 18) { - double val = char_to_long(result, strlen(result)); - recorder_print(0, "%.3f\n", val / 1000000000000000000L); - } - else if (!force_hex && result[0] == '0' && result[1] == 'x' && strlen(result) <= 18) - recorder_print(0, "%" PRIu64 "\n", char_to_long(result, strlen(result))); + // otherwise we add it to the params + if (args->len > 1) sb_add_char(args, ','); + if (*argv[i] >= '0' && *argv[i] <= '9' && *(argv[i] + 1) != 'x' && strcmp(method, "in3_toWei") && c->chain.chain_id != CHAIN_ID_BTC) + sb_print(args, "\"%s\"", get_wei(argv[i])); else - recorder_print(0, "%s\n", result); + sb_print(args, + (argv[i][0] == '{' || argv[i][0] == '[' || strcmp(argv[i], "true") == 0 || strcmp(argv[i], "false") == 0 || (*argv[i] >= '0' && *argv[i] <= '9' && strlen(argv[i]) < 16 && *(argv[i] + 1) != 'x')) + ? "%s" + : "\"%s\"", + strcmp(method, "in3_ens") ? resolve(c, argv[i]) : argv[i]); } } + sb_add_char(args, ']'); + + // start the server? + if (!method) check_server(c); + + // handle special cmd-methods + if (handle_rpc(c, &method, args, argc, argv)) recorder_exit(0); + + // execute + in3_log_debug("..sending request %s %s\n", method, args->data); + char *result = NULL, *error = NULL; + send_request(c, argc, argv, method, args, &result, &error); + + if (error) + die(error); + else if (!result) + die("No result"); + else + display_result(method, result); recorder_exit(0); -} +} \ No newline at end of file diff --git a/c/src/cmd/in3/main2.c b/c/src/cmd/in3/main2.c deleted file mode 100644 index 805462e66..000000000 --- a/c/src/cmd/in3/main2.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "../../init/in3_init.h" -#include "../../nodeselect/full/nodelist.h" -#include "../../nodeselect/full/nodeselect_def.h" -#include "handlers.h" -#include "helper.h" -#include "req_exec.h" -#include "transport.h" -#include "tx.h" - -static void send_request(in3_t* c, int argc, char** argv, char* method, sb_t* args, char** result, char** error) { - sb_t* sb = sb_new("{\"method\":\""); - sb_add_chars(sb, method); - sb_add_chars(sb, "\",\"params\":"); - sb_add_chars(sb, args->data); - char* ms_sigs = get_argument(argc, argv, "-sigs", "--ms.signatures", true); - if (ms_sigs) { - sb_add_chars(sb, ",\"in3\":{\"msSigs\":\""); - sb_add_chars(sb, ms_sigs); - sb_add_chars(sb, "\"}}"); - } - else - sb_add_chars(sb, "}"); - in3_client_rpc_raw(c, sb->data, result, error); - check_last_output(); -#ifdef NODESELECT_DEF - in3_chain_t* chain = &c->chain; - in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); - // Update nodelist if a newer latest block was reported - if (chain && nl->nodelist_upd8_params && nl->nodelist_upd8_params->exp_last_block) { - char *r = NULL, *e = NULL; - if (chain->type == CHAIN_ETH) - in3_client_rpc(c, "eth_blockNumber", "[]", &r, &e); - } -#endif -} - -int main(int argc, char* argv[]) { - // we want to verify all - in3_log_set_level(LOG_INFO); - - // define vars - char* method = NULL; - sb_t* args = sb_new("["); - in3_t* c = in3_for_chain(CHAIN_ID_MAINNET); - - init_transport(c); - init_recorder(&argc, &argv); - init_env(c, argc, argv); - - // parse arguments - for (int i = 1; i < argc; i++) { - // is it a argument? - if (configure_arg(c, argv, &i, argc)) continue; - - // now handle arguments for special methods - if (method == NULL) - method = argv[i]; - else if (strcmp(method, "sign") == 0 && !get_txdata()->data) - get_txdata()->data = b_new((uint8_t*) argv[i], strlen(argv[i])); - else if (get_txdata()->sig == NULL && (strcmp(method, "call") == 0 || strcmp(method, "send") == 0 || strcmp(method, "abi_encode") == 0 || strcmp(method, "abi_decode") == 0)) - get_txdata()->sig = argv[i]; - else { - // otherwise we add it to the params - if (args->len > 1) sb_add_char(args, ','); - if (*argv[i] >= '0' && *argv[i] <= '9' && *(argv[i] + 1) != 'x' && strcmp(method, "in3_toWei") && c->chain.chain_id != CHAIN_ID_BTC) - sb_print(args, "\"%s\"", get_wei(argv[i])); - else - sb_print(args, - (argv[i][0] == '{' || argv[i][0] == '[' || strcmp(argv[i], "true") == 0 || strcmp(argv[i], "false") == 0 || (*argv[i] >= '0' && *argv[i] <= '9' && strlen(argv[i]) < 16 && *(argv[i] + 1) != 'x')) - ? "%s" - : "\"%s\"", - strcmp(method, "in3_ens") ? resolve(c, argv[i]) : argv[i]); - } - } - sb_add_char(args, ']'); - - // start the server? - if (!method) check_server(c); - - // handle special cmd-methods - if (handle_rpc(c, &method, args, argc, argv)) recorder_exit(0); - - // execute - in3_log_debug("..sending request %s %s\n", method, args->data); - char *result = NULL, *error = NULL; - send_request(c, argc, argv, method, args, &result, &error); - - if (error) - die(error); - else if (!result) - die("No result"); - else - display_result(method, result); - recorder_exit(0); -} \ No newline at end of file From a48328f71676cbb3c3316184fb09808713e9f008 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 22:29:03 +0200 Subject: [PATCH 058/221] fix setting chainId --- c/src/core/client/client_init.c | 4 +- c/test/testdata/cmd/btc_bip34.txt | 200 ++---------------------------- 2 files changed, 13 insertions(+), 191 deletions(-) diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c index bc66dad66..f769b6cd0 100644 --- a/c/src/core/client/client_init.c +++ b/c/src/core/client/client_init.c @@ -261,12 +261,10 @@ char* in3_configure(in3_t* c, const char* config) { ct_ = chain_type(ct_token); EXPECT_TOK(ct_token, ct_ != -1, "expected (btc|eth|ipfs|)"); } - else - ct_ = chain_type_from_id(c->chain.chain_id); bool changed = (c->chain.chain_id != chain_id(token)); c->chain.chain_id = chain_id(token); - c->chain.type = (uint8_t) ct_; + c->chain.type = (uint8_t)(ct_ == -1 ? chain_type_from_id(c->chain.chain_id) : ct_); in3_client_register_chain(c, c->chain.chain_id, c->chain.type, 2); if (changed) in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); } diff --git a/c/test/testdata/cmd/btc_bip34.txt b/c/test/testdata/cmd/btc_bip34.txt index 57e7c3a41..1034ccba7 100644 --- a/c/test/testdata/cmd/btc_bip34.txt +++ b/c/test/testdata/cmd/btc_bip34.txt @@ -1,198 +1,20 @@ -:: cmd ./bin/in3 -x -fi ../c/test/testdata/cmd/btc_bip34.txt -c btc -nl http://localhost:8500 -f 5 getblockheader 000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb true -debug -rc 1 -a 1 +:: cmd bin/in3 -x -fi ../c/test/testdata/cmd/btc_bip34.txt -c btc -nl http://localhost:8500 -f 5 getblockheader 000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb true -debug -rc 1 -a 1 -:: time 1612516368 +:: time 1617222454 -:: rand 1138659513 - -:: rand 1223656574 - -:: rand 1692635546 - -:: rand 409749813 - -:: rand 1832534809 - -:: rand 202069589 - -:: rand 1011936416 - -:: rand 1692343119 - -:: request http://localhost:8500 - [{"id":2,"jsonrpc":"2.0","method":"in3_nodeList","params":[0,"0x43de90b948ef847e64e3919a186c49356d3a43190c0b56553c50eca064df1b4f",[],true],"in3":{"verification":"proof","version": "2.1.0","chainId":"0x99","finality":5,"preBIP34":true}}] - -:: response in3_nodeList 0 http://localhost:8500 0 6 -[{ - "id":2, - "result":{ - "nodes":[{ - "url":"https://in3-v2.slock.it/btc/nd-1", - "address":"0x45d45e6ff99e6c34a235d263965910298985fcfe", - "index":0, - "deposit":"0x2386f26fc10000", - "props":"0x2000001dd", - "timeout":3456000, - "registerTime":1593440588, - "weight":2000, - "performance":{ - "count":1, - "total":198, - "last_failed":0 - } - }, - { - "url":"https://in3-v2.slock.it/btc/nd-2", - "address":"0x1fe2e9bf29aa1938859af64c413361227d04059a", - "index":1, - "deposit":"0x2386f26fc10000", - "props":"0x2000001dd", - "timeout":3456000, - "registerTime":1593440633, - "weight":2000, - "performance":{ - "count":1, - "total":3201, - "last_failed":1612516223542 - } - }, - { - "url":"https://in3-v2.slock.it/btc/nd-3", - "address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4", - "index":2, - "deposit":"0x2386f26fc10000", - "props":"0x2000001dd", - "timeout":3456000, - "registerTime":1593440648, - "weight":2000, - "performance":{ - "count":1, - "total":195, - "last_failed":0 - } - }, - { - "url":"https://in3-v2.slock.it/btc/nd-4", - "address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8", - "index":3, - "deposit":"0x2386f26fc10000", - "props":"0x2000001dd", - "timeout":3456000, - "registerTime":1593440678, - "weight":2000, - "performance":{ - "count":1, - "total":3326, - "last_failed":1612516223542 - } - }, - { - "url":"https://in3-v2.slock.it/btc/nd-5", - "address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2", - "index":4, - "deposit":"0x2386f26fc10000", - "props":"0x2000001dd", - "timeout":3456000, - "registerTime":1593440708, - "weight":2000, - "performance":{ - "count":1, - "total":3220, - "last_failed":1612516223542 - } - }], - "contract":"0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32", - "registryId":"0x53786c93e54c21d9852d093c394eee9df8d714d8f2534cdf92f9c9998c528d19", - "lastBlockNumber":4229185, - "totalServers":5 - }, - "jsonrpc":"2.0", - "in3":{ - "execTime":0, - "proof":{ - "type":"accountProof", - "block":"0xf9025ca076d3a4a758090c66b136b2b719a94d2823bc0be8d1172b23fbfda179bebcc96aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0b5d5f066b66d451b5d5cf3395150122568c66c865766b17f3a83e2e4a211586fa04dbdc0f0e921e2e95988a8c725af395cc3d25314ade9ad412f809fd96af1be45a03fcc60c369a34f1fbf6611e71daa0d11f25e66a09c26237087d65c38a0719a79b90100008000000000000000000000008001000000800000000800008000000000000004000000000000040000008000004000000000000800000400000000000000000000000000001020000000090000008042014000000000000000200000000010000000000210000000000000000008040000000000000000000000100000104000000000000000000000400000000000000000000000000000000000010000001000020000000000000000000000000000000001000800000000000000000000000000020010000010000000200000000000200000000000000000000000200000000000000000100000000000000400000000000000000000000000000000000283408841837a1200831aae9884601d0b7cb861000000000000436f6e73656e5379732048797065726c65646765722042657375a93e60140d01945fb8a233a4eedab42b61e0e5c4e7ec25267ec0fd74b481351f5a397679d36ddbc97fd85abd7286ceb63b656bcdd83ebc7e7c8672faa53e541700a00000000000000000000000000000000000000000000000000000000000000000880000000000000000", - "accounts":{ - "0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32":{ - "accountProof":["0xf90211a02176c129dbc42e25c8d1162dc0edf92c2e65bee045d0c7560934438153406a6fa0e118fb12921b790d5a9ee1ad345c260ee3276cf850561658e1abe616baf40286a032517df96c207ceb6964b516f7cf7f54594ed433b0b5f032e362a550b38ad1ffa044b91c7c42e59fa635337b00d381c672bd2945c951e68cd1365ea485d4f37ec6a0e2d2af55418b8ef4f8d9c47f8a53f19b526294b9a97905c340b9cc6f620da301a00bceffcc6073b6cb383dca8d4f7f6abfe605b5e9f40838adc58105da6819319da01305e8d89582149cb08147b4a60bf98863b23c2708960782c29d986482faa388a024ba45083e5850966c3e760f95aec7d4004738f427c25a56c18439348dba9a23a0c40609f42e985bf7c1df75b26786528c4e4ea09a275f01f8704d720a7284e038a03989be34cb23145de7bbdfa095868575dd527202ce41a256b5c84e5582080be9a05f22ae2af2734025efc73c0b5c60329126733cefe03c9f57b0e9170da2264f43a0a86f752f84985ae46c715dd6de83cadeb8491a05442c1c2a490564e496adf8a1a09ba64dbea55976d707883e43c019cc6d94c49b8f6ae65099bda01c84c3888e4fa09296cf138f05ea04341e823d682a7cda889a3f80270725479b40733701db7f0ba0139fdc9eed3c2d025283d6dd4afaddde0919161f51a4ca7e0f2c8495017b7733a0543a55b212f31fa4009ae14c9008a142fd9629442a1dbb886a97c6a9e709b9fc80", - "0xf90211a0ed9c0ff9ae751d881c84a357918739f10525eed27b43de0f9296e5baaf9bb1fda0e0128203a2f634bd2bc3bedfd6bcf164f69f5fbe94c87c05d4908a37a1f81d46a08f3fd424a0c6719514dbef79e1e849c24f39f4239ecdf665c73116c152e09050a0979a57a7ecbc9018043f0d9edeacf3965f5cb9487aa243a016eaabff06740189a0b21b702577cd8579103422d551d85efb638172bc54fc55a75693b5a2fdfdc54fa09b6d19191d8d09916c9fbd3f819173caa43709c5b7041998bef417b2b7515ceda0b210d6ba8e1162dde71877ae2c8a5c9c16137efa662cec3e627d6a9645c0cd44a0acf80531cc4b674c58a4c9faf0fa63034e861b85c8613947da582fec5f1dee68a019cc0bc1c987814d96d15898ef1ec3dfff19b10fb41bbdc7f39eb39182833672a0926bf31e6b8575ca40a55b33717965ccee9500be55c525586d17138bc3d1e43fa0b35f96a10bf3126d6ed21b8cf400e9b1d94ee828dcfce3544462ab21d0c2d6aea00676b7047bfe5e74da9f04b0e58ac0624b60160496dd79f1530d2beb4a6e5350a09c5f723923cdc360a9f7e0e1200fe8f82967e6c1ecac06b94f2d9252204d6caea08799003a84ec35a486ec5d520bc160b57c62c6eb4f8117e0c69ca5cd1ac23440a0a3bfea660692e188e4cf88d78efc21868418c58b43aa51d15afbeaeb5a30ea90a0327f99800e8d4d5146898d0eb401ee4f967f0c62b98014a96efd248d71cb273f80", - "0xf90211a0c52b7d7c9faa8fc42e3843e59b0c7102188d918840b8b5cf5649197b13942a94a067f59108675f198f0b1f14273b4fbb3ba4c9ac61ecaa83900e37154881990941a08407f24415d4b1971faa2f1e53d2cfbb4fae100d135486236834036b94d129fca0cdf5918e749c6ed171d0e1db4a39df01763c7a2e7b0429b304f5de22d16195e8a01efdf7379329d0d371efabd4fa76401f1984fcbca64471ebe2c74475845f0a85a0a28daa09319d9b64e5967130cdd21a099b54869ddf92dff7cc080bbb25279364a0cea9a3f62b9e510d5508f3ca8323dd519cae9c320f99dc172193d07f0c6317b3a0369809678111f01bbcdcd5df6c6a2841e85077206e3b650db6eb2ec037e13a2da0e7511971b817dd5f0241d0309cd6f8e8e9ad35aba0807204884e840c16f4471ca06d6da5d6f453b1ea3dc911431e9a26abc197b409538aa40d46da259e6c08729aa0a5edc7f66811fa983d4e2d61c09fbc50bdefb4d77c487eb1ac533ceab3bcaf09a06e6f4a8927f13aadfb9c772b0715bcfe313f02b6034b0d6f2b59f56e0b9c9c3ba0763f63c10c5e3334c7b3af8f419f8add4e1f85f7cfcedea3f06912d66840c1fda05286d33d2797793fca9d99ece2f764da00716ac9536c635c83c695ed84a0e4d3a0079a7452891f1b97eccbb9bd876353da6732910c99194953c3e392265a6a0712a0d729c7014af2776b688d09d312623bb74cb092c92aafa099bdac3c6a1f53e39980", - "0xf90211a037a3337f0005db74a91f0f96ff9fbacbbc0521a8784b3ff8c9d8444d81e20456a075183b26afb188dcbbeee102e53d7ecf7f9b82c92c0d6efce4ff73c2fc9427eea0fe890d643ed692fa36be93853f94be950f7c57367fc9a3fd19fdfa76fbcd084ea06335914313fc71923c429c0a768c0584f2486976aaf5ae6e939cc0c1819c678fa0cc46707e8dab2140eabb4c2af2c8ae392674ac306f8608037e5afecd026b76b1a0910c8d52ee6bafc81d8033360f056cd845e15a87fbfd52d58daa576b58e9e39aa0db792420e982fc3088994c2fecc5271dae872a7743d8e9509b211c5d4e47bc8ca05eaa1847e192dda347bb7f272485e67f55925df2ad747e9faacc02ba12dd9d2da0a4437a739941a0a53d690f63cf5154030f1786944b7db70b224ad3bc3185725da0cd2436f554561a620f05eccc2cf101540161a3e3f5cd0b850602ece78b39e70da0ea6d47e623b880d04163a1976acd454e44ae57cfacda98a3757ae4350eead60ca0b696d8434f73dce704ab08de53ff772e86f50cfcc1a752002d1e0e5726308679a0a25b9334ba25fbd904b35fdc0063cca2be2817ce508108687a48c9020ff3aa5aa051ffa5e10005f382bbc6b388e200037bb41bbef652137761d8a317ffabaf2b3aa0abb3708f4efc71f63d4d3c45fdfb616da97646b412d79c134f58e64795cebde0a09b81a3cbbf7eeefcafae4f0163f51303c2708f20870dc23edf905da4aa8e522280", - "0xf90131808080a0615059ed3d0c135089a399e39e1108e5f58fc040d20bb1594d327d565f6530dfa0cca3258088afed6e4228125045d2813d736c800bc9551b38e99a228fb4985334a0b8609eb04093c8652ac25cf5d412d366616c55d78e769d0133a4e11baaf51c9480a071319005086e17af8200acfdcdaaac0d39b3a30daafb102cb1e81787a5671246a0d623ac3203b39d02c36962fae8246e75cfc6eb03d9ec358115794e0ef967b7d8a0005374980c9eb696e134af89e55bec93767d19fbc7eacdfb423865e28fb853d98080a0a7f8317e21a74ea5c5ade1f3cfe5b019caf1e5df49c0e6063fe477a7a3e7e79c80a05adcf071a5adcb1c99f67df461650b2ba62d3f48600f4b97e6b1201194288702a05db46c9db1409a03378debec1d3daf79a6365672e7ca0b1902e158d3b18355ea80", - "0xf8679e3dfa35139af4f993370c1dc5c729942db777d38a285fb227906c1bc93854b846f8440180a04d736bfa42e5592b521061863e73c096fb378444a82b1a057e240b863c90666ea029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"], - "address":"0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32", - "balance":"0x0", - "codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1", - "nonce":"0x1", - "storageHash":"0x4d736bfa42e5592b521061863e73c096fb378444a82b1a057e240b863c90666e", - "storageProof":[{ - "key":"0x0", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf891a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e8808080808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a081b7693d9ef9dea4b83b27e12fd4a86cfd861c266865545c3602ec6a1e43039da0aa7f3523263242a60b36be40eabda7dae87817cbb0cdbf6948564d446d43cae0808080808080", - "0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56305"], - "value":"0x5" - }, - { - "key":"0x1", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf85180a083500cde7f6fd365be906592de84b1d7b3bbb1fc02e2129051371bf3adb79eed808080808080808080808080a008ce5962e734b12d09863c498b32a8f4b2078bf5b414ae7ee0fa3a57e2b6b3a48080", - "0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a053786c93e54c21d9852d093c394eee9df8d714d8f2534cdf92f9c9998c528d19"], - "value":"0x53786c93e54c21d9852d093c394eee9df8d714d8f2534cdf92f9c9998c528d19" - }, - { - "key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf871a0a28c08659e018bd7c2c18c6275f97881c4d7c045943c5caecfea71e41474cc9e8080808080808080808080a0407e55e9a8f7681ee1a46fd778e03ffd2fa7507952c81308e60239bbaba3875a80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080", - "0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a013218ee8dd11494c58f119748f198ad3c24a0024746f3a5896f51dc1e008821f"], - "value":"0x13218ee8dd11494c58f119748f198ad3c24a0024746f3a5896f51dc1e008821f" - }, - { - "key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf8718080a004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080808080808080a0db8ab81a65a81b2ff2c25e14082cc52fa19e16339b5d616a4a7749e830bf136780a03f40fdc942ec4a9b8cf72f3599a83e4b40cf9f76905977c6e9cf1d93e3485a7b808080", - "0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a091605b26d5a69917787d9bcac74f808951039567c0db700da087a92a4e9a6072"], - "value":"0x91605b26d5a69917787d9bcac74f808951039567c0db700da087a92a4e9a6072" - }, - { - "key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf871a0d3b9189299e575e9b50d9e6113d15c202e7dd53942477ff21ac5a62e5b5fcd018080a08a0a0e6297b603d3e5577d7e849031cfba639f44aa9f27a34b6e4b950c6c073a808080808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd0808080808080", - "0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a0855e7bdf0b02683e5ab1cdc096c6101085b4c7fe69fe218bffa7dff912490a9b"], - "value":"0x855e7bdf0b02683e5ab1cdc096c6101085b4c7fe69fe218bffa7dff912490a9b" - }, - { - "key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf85180a083500cde7f6fd365be906592de84b1d7b3bbb1fc02e2129051371bf3adb79eed808080808080808080808080a008ce5962e734b12d09863c498b32a8f4b2078bf5b414ae7ee0fa3a57e2b6b3a48080", - "0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a0b28786a66e4e84e2b7e236efb9fb0a82053e342cbf26d41af8c4cae4836d56e8"], - "value":"0xb28786a66e4e84e2b7e236efb9fb0a82053e342cbf26d41af8c4cae4836d56e8" - }, - { - "key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b", - "proof":["0xf90211a0c1d22c4f4f1cc6ad83407a19b0bf3b129206880b89a580d09ec7151ad9886095a053147b12a82ecbbf958ea21eaaa2b4b5e676963a1753f0e1c817c7cfe8ea48ada0076fff6235c18f210b8221a89fed3f6722f69f20f36341bae5e8da877284000fa0551e4cfb868bba75b151be76c2da75e52824e15c501c0000ba044250a971176fa012a4969e387686fc86af25c07f72fbd658df39b133002d50a19ada8a8c005b9da0e2665b2ac7f21c0d77a88b8ffe7eb97fc247c768d77f8e49e518f7ef949d3989a00916ff25b14411517799d32a46128fd65ee9c90208563ffc6ca52e654673f1b6a07f67f5182dfcdcd333dbe5418dd1372f57ef648defa506aa4b8939d9e87b8fd8a0cee9a05be79629c249555cca89bead566bbf2a791de2729a3f37c4795b0ef3b2a0e07263f33741ea2779a238a95b43c60fe85c1f5c55ccfbe71202a5270e8d4b6ba05f03c75d89c4a70dfe72980c3c740155d12bc07edaca4300153d9f74b6b3624aa0be3f6a3c5587a2e321d2e6a766518c8966e311f921e1936906920fed463ec8b1a078dc7aa0d2de98f73391cda3066e6c4dec84c1ffa840b234b7081ca5ddebd4fea01d8b2a194aeacedef6268d6bf81d351fd0e2177ae007c5201ff7c10e9716d5c4a0f09b315bf02379572d599d47a7610f96feb1b72dd98123a1f47ac8e9750862c2a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80", - "0xf871a0a28c08659e018bd7c2c18c6275f97881c4d7c045943c5caecfea71e41474cc9e8080808080808080808080a0407e55e9a8f7681ee1a46fd778e03ffd2fa7507952c81308e60239bbaba3875a80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080", - "0xf85180808080a02ae042c128229c068ee987ed30164a035d10da3ba96f25b04b7e56e6fc2c12fb808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080", - "0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0986891b6cd760bac247ed5d7dbc574b1c07425bc49a44d54b9900dc485329218"], - "value":"0x986891b6cd760bac247ed5d7dbc574b1c07425bc49a44d54b9900dc485329218" - }] - } - } - } - } -}] - -:: cache btc_target_153 1 -000affff001d000fffff001d00145746651c0019a7bc201c001e64ba0e1c00235a0c011c0028ed66471b002d56720e1b0032cb04041b0037cd2d011b003cfa98001b00418521131a0046864a091a004bcaf00d1a0050d7690d1a005587320b1a005a5f8b0a1a005fc93c081a0064087e051a006962fa041a006e5c98041a007394de011a007815de001a007d328754190082cab01619008742120619008c2cf50119009199db0019009642286918009ba2ae3a1800a093b81f1800a5747b1b1800aa87bb181800aff017171800b48e41161800b9c14d131800be89b2101800c31bb3091800c8c3a4061800cd3684051800d22872051800d7c440041800dc858b031800e1937e021800e63e1b021800eb308d011800f00b31011800f54bce001800fa8c577e1700ff494a51170104495a411701097b4f2f17010e91c125170113f41e37170118505b2e17011d38ff291701229b0d1f170127f5ab1717012c3eb215170131ff3212170136bc2013170135413b1417 +:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 +07000000000043a3e5000000050000000000000000000000000000000001000000450100000000000000000000eb06000091e601008051010000000000eb060000883802008051010000000000eb0600005a3a020080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6274632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6274632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6274632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6274632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6274632f6e642d350000000000 :: request http://localhost:8500 [{"id":1,"jsonrpc":"2.0","method":"getblockheader","params":["000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb",true],"in3":{"verification":"proof","version": "2.1.0","chainId":"0x99","finality":5,"preBIP34":true}}] -:: response getblockheader 0 http://localhost:8500 0 129 +:: response getblockheader 0 http://localhost:8500 0 489 [{ "id":1, "jsonrpc":"2.0", "result":{ "hash":"000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb", - "confirmations":646406, + "confirmations":654404, "height":22790, "version":1, "versionHex":"00000001", @@ -212,14 +34,16 @@ "final":"0x01000000bbd4c33d13ab278ed48ec103777bf8d5fd261ce798e6780d0eaffc2a00000000d661462f180562c74d25efb0c007d6b4b20fe10b61adecad7484c3c53fde0e41c3dfac4affff001dba4db74d01000000fcdbcd016be8773a777ba924c6468a2c1cc4d020fdbdf13aec9f43c80000000014104745e906313add5762734b11a44e64ea7a35fce3b448365ae3e4e3161d1988e5ac4affff001d149df3dd01000000ceda3913875fad030d3ab752a2c95893e66958fa34c164cffe6e73da00000000b2d841452e2a7117753c423f049cbbe0d13dacdb99266880407e26282ea53d3d3aeaac4affff001d16343a420100000032b5d55ed9667e77bc11c7f3e16503ea184e146cdb3bd290cbd85e83000000003177ded1cce03952f1fc214b3930d6de33186d5a72a5c8c0c9e38ed608fac76f88f0ac4affff001d20e3ad500100000023c81d5fa8eb67ceccc8d42262c900ecb60b2c080865d3eb6e2bdf44000000007120278a4a79ccc46a29f6ec819485c6d04f20c721c0a4e0d1364f1e007eae505af2ac4affff001d0031144a01000000e8b8406cadca24f4be8feac6c2cd1ec21e0c134504e4874807092b6c00000000aa7fbe13f0d870c298a54dc0624375d728557b7f8f6a6c88f58b71a056dc90c542f8ac4affff001d08ffb3d001000000ffe8566bb6808828e251ec3dc6081c335f3a039f6ed4e7143d509ea500000000c2f7dfa0221a15512cb99ea2c193eb39c5c181c840204b623ffde6e17c4e5e47aefaac4affff001dc2bdcc11010000000a77bb0ff642c5c568a7f5440c11f0ddd04fd801d2a66a3325f5ce25000000003b846ebf084baa6a1dbd88ce761c793d21afb86588a1e285d050c3b6f1e8fc657bfcac4affff001d2080bb670100000030ff49d95072dcc9f78301ceeaf43e13c84d8250cb07229c61be5ef20000000005abf988b99ad4199b5122701452117f2328f3c1051678090fc452d8d319ec710404ad4affff001d1fec09660100000079ff834d61ea4c6264612c58d5853fc0392a5c4ded52c797e033a2d9000000008aea365a64ae3664861ed730c087d263d28273ae70c086fc55c211fed8e64d78310dad4affff001d176d900c", "height":22790 }, - "lastNodeList":4229185, - "execTime":125, + "lastNodeList":4539052, + "execTime":437, "rpcTime":0, "rpcCount":0, - "currentBlock":4229194, + "currentBlock":4539053, "version":"2.1.0" } }] +:: cache btc_target_153 0 + :: result -{"hash":"000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb","confirmations":646406,"height":22790,"version":1,"versionHex":"00000001","merkleroot":"a2d99d38724cfb8bc7bf25b69278be0511dcc8229280b3d28144ed61c312a542","time":1252839569,"mediantime":1252834756,"nonce":231526776,"bits":"1d00ffff","difficulty":1,"chainwork":"0000000000000000000000000000000000000000000000000000590759075907","nTx":1,"previousblockhash":"0000000081a33fec1ece434279ddc7c59a00c7a4ec2f08db452bade37d50be75","nextblockhash":"00000000c8439fec3af1bdfd20d0c41c2c8a46c624a97b773a77e86b01cddbfc"} +{"hash":"000000002afcaf0e0d78e698e71c26fdd5f87b7703c18ed48e27ab133dc3d4bb","confirmations":654404,"height":22790,"version":1,"versionHex":"00000001","merkleroot":"a2d99d38724cfb8bc7bf25b69278be0511dcc8229280b3d28144ed61c312a542","time":1252839569,"mediantime":1252834756,"nonce":231526776,"bits":"1d00ffff","difficulty":1,"chainwork":"0000000000000000000000000000000000000000000000000000590759075907","nTx":1,"previousblockhash":"0000000081a33fec1ece434279ddc7c59a00c7a4ec2f08db452bade37d50be75","nextblockhash":"00000000c8439fec3af1bdfd20d0c41c2c8a46c624a97b773a77e86b01cddbfc"} From ffa75b1d253fd8fbf85d3f0d4f4a43c12de17f26 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 22:29:46 +0200 Subject: [PATCH 059/221] format args --- c/src/cmd/in3/args.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 53c560f3c..534eb5ab3 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,7 +2,7 @@ #include -const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ From 54b0a28d8df46fc5e48167799106ceed6f8d8581 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 22:43:26 +0200 Subject: [PATCH 060/221] fix no transport --- c/src/cmd/in3/transport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/src/cmd/in3/transport.c b/c/src/cmd/in3/transport.c index fb5da4d21..623f1ce36 100644 --- a/c/src/cmd/in3/transport.c +++ b/c/src/cmd/in3/transport.c @@ -1,3 +1,4 @@ +#include "../../core/client/request_internal.h" #include "helper.h" #ifdef USE_CURL #include "../../transport/curl/in3_curl.h" From 355eb7f3e4733a1f14586adf1b1a580c181b233e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 22:44:40 +0200 Subject: [PATCH 061/221] fix warning --- c/src/cmd/in3/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/transport.c b/c/src/cmd/in3/transport.c index 623f1ce36..4518314d4 100644 --- a/c/src/cmd/in3/transport.c +++ b/c/src/cmd/in3/transport.c @@ -69,7 +69,7 @@ static in3_ret_t test_transport(void* plugin_data, in3_plugin_act_t action, void #elif TRANSPORTS in3_ret_t r = send_http(NULL, action, plugin_ctx); #else - in3_ret_t r = plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; + in3_ret_t r = action && plugin_ctx != NULL ? IN3_OK : IN3_ECONFIG; #endif if (r == IN3_OK) { req->payload[strlen(req->payload) - 1] = 0; From 013fe76a558dd52986fc1f247bbae60268ce9de2 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 22:50:13 +0200 Subject: [PATCH 062/221] fix gcc warning --- c/src/core/client/client_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c index f769b6cd0..2a80fa699 100644 --- a/c/src/core/client/client_init.c +++ b/c/src/core/client/client_init.c @@ -264,7 +264,7 @@ char* in3_configure(in3_t* c, const char* config) { bool changed = (c->chain.chain_id != chain_id(token)); c->chain.chain_id = chain_id(token); - c->chain.type = (uint8_t)(ct_ == -1 ? chain_type_from_id(c->chain.chain_id) : ct_); + c->chain.type = ct_ == -1 ? chain_type_from_id(c->chain.chain_id) : ((in3_chain_type_t) ct_); in3_client_register_chain(c, c->chain.chain_id, c->chain.type, 2); if (changed) in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); } From 93931e3c7a337f7ff9e82879d3a7921fc68ec284 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 23:07:37 +0200 Subject: [PATCH 063/221] fix gcc warning --- c/src/cmd/in3/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c index 805462e66..d10a7cb89 100644 --- a/c/src/cmd/in3/main.c +++ b/c/src/cmd/in3/main.c @@ -26,7 +26,7 @@ static void send_request(in3_t* c, int argc, char** argv, char* method, sb_t* ar in3_chain_t* chain = &c->chain; in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); // Update nodelist if a newer latest block was reported - if (chain && nl->nodelist_upd8_params && nl->nodelist_upd8_params->exp_last_block) { + if (chain && nl && nl->nodelist_upd8_params && nl->nodelist_upd8_params->exp_last_block) { char *r = NULL, *e = NULL; if (chain->type == CHAIN_ETH) in3_client_rpc(c, "eth_blockNumber", "[]", &r, &e); From b8d31cd298da831ce15f9aa417271623c357988e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 31 Mar 2021 23:57:28 +0200 Subject: [PATCH 064/221] fix gcc warning --- c/src/cmd/in3/option_handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/option_handler.c b/c/src/cmd/in3/option_handler.c index c3736144f..4b267248f 100644 --- a/c/src/cmd/in3/option_handler.c +++ b/c/src/cmd/in3/option_handler.c @@ -62,7 +62,7 @@ static bool set_nodelist(in3_t* c, char* nodes, sb_t* sb, bool update) { if (!update) c->flags = FLAGS_STATS | FLAGS_BOOT_WEIGHTS | (c->flags & FLAGS_ALLOW_EXPERIMENTAL); char* cpy = alloca(strlen(nodes) + 1); in3_nodeselect_def_t* nl = in3_nodeselect_def_data(c); - if (!update && nl->nodelist_upd8_params) { + if (!update && nl && nl->nodelist_upd8_params) { _free(nl->nodelist_upd8_params); nl->nodelist_upd8_params = NULL; } From bcae781eed0e9ee1128c62f8fc82d622c84e2928 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 1 Apr 2021 01:12:29 +0200 Subject: [PATCH 065/221] handle requestCount 2 error --- c/src/core/client/execute.c | 68 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c index a247b76ff..eb85fab21 100644 --- a/c/src/core/client/execute.c +++ b/c/src/core/client/execute.c @@ -722,6 +722,15 @@ static void in3_handle_rpc_next(in3_req_t* ctx, ctx_req_transports_t* transports } } + // looks like we were not able to send out the first request, so waiting for the second won't help. + node_match_t* w = ctx->nodes; + for (int j = 0; w; j++, w = w->next) { + if (ctx->raw_response[j].state == IN3_WAITING && !ctx->raw_response[j].data.data) { + in3_ctx_add_response(ctx, j, IN3_ERPC, "The request could not be send!", -1, 1); + return; + } + } + req_set_error(ctx, "waiting to fetch more responses, but no cptr was registered", IN3_ENOTSUP); } @@ -741,45 +750,44 @@ void in3_handle_rpc(in3_req_t* ctx, ctx_req_transports_t* transports) { in3_log_trace("... request to " COLOR_YELLOW_STR "\n... " COLOR_MAGENTA_STR "\n", request->urls[i], i == 0 ? request->payload : ""); // handle it (only if there is a transport) - if (in3_plugin_execute_first(ctx, PLGN_ACT_TRANSPORT_SEND, request) == IN3_OK) { + in3_plugin_execute_first(ctx, PLGN_ACT_TRANSPORT_SEND, request); - // debug output - node_match_t* node = request->req->nodes; - for (unsigned int i = 0; i < request->urls_len; i++, node = node ? node->next : NULL) { - if (request->req->raw_response[i].state != IN3_WAITING) { - char* data = request->req->raw_response[i].data.data; + // debug output + node_match_t* node = request->req->nodes; + for (unsigned int i = 0; i < request->urls_len; i++, node = node ? node->next : NULL) { + if (request->req->raw_response[i].state != IN3_WAITING) { + char* data = request->req->raw_response[i].data.data; #ifdef DEBUG - data = format_json(data); + data = format_json(data); #endif - in3_log_trace(request->req->raw_response[i].state - ? "... response(%s): \n... " COLOR_RED_STR "\n" - : "... response(%s): \n... " COLOR_GREEN_STR "\n", - node ? node->url : "intern", data); + in3_log_trace(request->req->raw_response[i].state + ? "... response(%s): \n... " COLOR_RED_STR "\n" + : "... response(%s): \n... " COLOR_GREEN_STR "\n", + node ? node->url : "intern", data); #ifdef DEBUG - _free(data); + _free(data); #endif - } } + } - // in case we have a cptr, we need to save it in the transports - if (request && request->cptr) { - // find a free spot - int index = -1; - for (int i = 0; i < transports->len; i++) { - if (!transports->req[i].req) { - index = i; - break; - } - } - if (index == -1) { - transports->req = transports->len ? _realloc(transports->req, sizeof(ctx_req_t) * (transports->len + 1), sizeof(ctx_req_t) * transports->len) : _malloc(sizeof(ctx_req_t)); - index = transports->len++; + // in case we have a cptr, we need to save it in the transports + if (request && request->cptr) { + // find a free spot + int index = -1; + for (int i = 0; i < transports->len; i++) { + if (!transports->req[i].req) { + index = i; + break; } - - // store the pointers - transports->req[index].req = request->req; - transports->req[index].ptr = request->cptr; } + if (index == -1) { + transports->req = transports->len ? _realloc(transports->req, sizeof(ctx_req_t) * (transports->len + 1), sizeof(ctx_req_t) * transports->len) : _malloc(sizeof(ctx_req_t)); + index = transports->len++; + } + + // store the pointers + transports->req[index].req = request->req; + transports->req[index].ptr = request->cptr; } // we will cleanup even though the reponses may still be pending From 4826dc31950859d832d20d0b3299e6930d654a3a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 1 Apr 2021 09:24:03 +0200 Subject: [PATCH 066/221] better detect user-errors --- c/src/core/client/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c index eb85fab21..a5afc80b2 100644 --- a/c/src/core/client/execute.c +++ b/c/src/core/client/execute.c @@ -297,7 +297,7 @@ static bool is_user_error(d_token_t* error, char** err_msg) { *err_msg = d_type(error) == T_STRING ? d_string(error) : d_get_string(error, K_MESSAGE); // here we need to find a better way to detect user errors // currently we assume a error-message starting with 'Error:' is a server error and not a user error. - return *err_msg && strncmp(*err_msg, "Error:", 6) != 0 && strncmp(*err_msg, "TypeError:", 10) != 0; + return *err_msg && strncmp(*err_msg, "Error:", 6) != 0 && strncmp(*err_msg, "TypeError:", 10) != 0 && strncmp(*err_msg, "Error connect", 13) != 0; } NONULL static void clear_response(in3_response_t* response) { From a1b21e8b023d1c51a6804d68d48b5aac8a14baee Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 14:13:24 +0200 Subject: [PATCH 067/221] addded swift bindings --- .gitignore | 6 ++++ .gitlab-ci.yml | 2 ++ swift/In3/Package.swift | 27 ++++++++++++++++ swift/In3/README.md | 3 ++ swift/In3/Sources/In3/In3.swift | 29 +++++++++++++++++ swift/In3/Tests/In3Tests/In3Tests.swift | 17 ++++++++++ .../In3/Tests/In3Tests/XCTestManifests.swift | 9 ++++++ swift/In3/Tests/LinuxMain.swift | 7 +++++ swift/In3Sys/Package.swift | 18 +++++++++++ swift/In3Sys/README.md | 3 ++ swift/In3Sys/module.modulemap | 5 +++ swift/ci.yml | 31 +++++++++++++++++++ 12 files changed, 157 insertions(+) create mode 100644 swift/In3/Package.swift create mode 100644 swift/In3/README.md create mode 100644 swift/In3/Sources/In3/In3.swift create mode 100644 swift/In3/Tests/In3Tests/In3Tests.swift create mode 100644 swift/In3/Tests/In3Tests/XCTestManifests.swift create mode 100644 swift/In3/Tests/LinuxMain.swift create mode 100644 swift/In3Sys/Package.swift create mode 100644 swift/In3Sys/README.md create mode 100644 swift/In3Sys/module.modulemap create mode 100644 swift/ci.yml diff --git a/.gitignore b/.gitignore index 6a12fcf7d..32c669d10 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ bin/ .classpath .project *.class +python/**/*.pyc target/ .cproject .overcommit.yml @@ -49,3 +50,8 @@ c/src/third-party/hidapi/compile c/src/third-party/hidapi/aclocal.m4 c/examples/CMakeLists.txt c/.clang-format +swift/**/.DS_Store +swift/**/.build +swift/**/Packages +swift/**/*.xcodeproj +swift/**/xcuserdata/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f0441a1a9..c2156f71d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,6 +30,7 @@ stages: - python - dotnet - java + - swift - test - analysis - deploy @@ -46,3 +47,4 @@ include: - local: "/python/ci.yml" - local: "/dotnet/ci.yml" - local: "/rust/ci.yml" + - local: "/swift/ci.yml" diff --git a/swift/In3/Package.swift b/swift/In3/Package.swift new file mode 100644 index 000000000..dd6a853e2 --- /dev/null +++ b/swift/In3/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "In3", + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "In3", + targets: ["In3"]), + ], + dependencies: [ + .package(path: "../In3Sys"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "In3", + dependencies: []), + .testTarget( + name: "In3Tests", + dependencies: ["In3"]), + ] +) diff --git a/swift/In3/README.md b/swift/In3/README.md new file mode 100644 index 000000000..370ade086 --- /dev/null +++ b/swift/In3/README.md @@ -0,0 +1,3 @@ +# In3 + +A description of this package. diff --git a/swift/In3/Sources/In3/In3.swift b/swift/In3/Sources/In3/In3.swift new file mode 100644 index 000000000..ef95d7d9e --- /dev/null +++ b/swift/In3/Sources/In3/In3.swift @@ -0,0 +1,29 @@ +import In3Sys + +public class In3 { + var in3: UnsafeMutablePointer? = nil + + func makeCString(from str: String) -> UnsafeMutablePointer { + let count = str.utf8.count + 1 + let result = UnsafeMutablePointer.allocate(capacity: count) + str.withCString { (baseAddress) in + // func initialize(from: UnsafePointer, count: Int) + result.initialize(from: baseAddress, count: count) + } + return result + } + + public init(config: String) { + in3 = in3_for_chain_auto_init(1) + in3_configure(in3, config) + } + + deinit { + in3_free(in3) + } + + public func execute(rpc: String) -> String { + return String(cString: in3_client_exec_req(in3, makeCString(from: rpc))) + } +} + diff --git a/swift/In3/Tests/In3Tests/In3Tests.swift b/swift/In3/Tests/In3Tests/In3Tests.swift new file mode 100644 index 000000000..d852d16c1 --- /dev/null +++ b/swift/In3/Tests/In3Tests/In3Tests.swift @@ -0,0 +1,17 @@ +import XCTest +@testable import In3 + +final class In3Tests: XCTestCase { + func testExample() { + let in3 = In3(config: "{\"chainId\":\"mainnet\"}") + let res = in3.execute(rpc: "{\"method\":\"keccak\",\"params\":[\"simon\"]}") + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + XCTAssertEqual(res , "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a\"}") + } + + static var allTests = [ + ("testExample", testExample), + ] +} diff --git a/swift/In3/Tests/In3Tests/XCTestManifests.swift b/swift/In3/Tests/In3Tests/XCTestManifests.swift new file mode 100644 index 000000000..1b5c3d87c --- /dev/null +++ b/swift/In3/Tests/In3Tests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(In3Tests.allTests), + ] +} +#endif diff --git a/swift/In3/Tests/LinuxMain.swift b/swift/In3/Tests/LinuxMain.swift new file mode 100644 index 000000000..85e300a77 --- /dev/null +++ b/swift/In3/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import In3Tests + +var tests = [XCTestCaseEntry]() +tests += In3Tests.allTests() +XCTMain(tests) diff --git a/swift/In3Sys/Package.swift b/swift/In3Sys/Package.swift new file mode 100644 index 000000000..17cde3155 --- /dev/null +++ b/swift/In3Sys/Package.swift @@ -0,0 +1,18 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "In3Sys", + products: [ + .library(name: "In3Sys", targets: ["In3Sys"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + .systemLibrary(name: "In3Sys"), + ] +) diff --git a/swift/In3Sys/README.md b/swift/In3Sys/README.md new file mode 100644 index 000000000..0cd1c5c51 --- /dev/null +++ b/swift/In3Sys/README.md @@ -0,0 +1,3 @@ +# In3Sys + +A description of this package. diff --git a/swift/In3Sys/module.modulemap b/swift/In3Sys/module.modulemap new file mode 100644 index 000000000..a9de6e82f --- /dev/null +++ b/swift/In3Sys/module.modulemap @@ -0,0 +1,5 @@ +module In3Sys [system] { + header "../../c/include/in3.rs.h" + link "in3" + export * +} diff --git a/swift/ci.yml b/swift/ci.yml new file mode 100644 index 000000000..e108ceaaf --- /dev/null +++ b/swift/ci.yml @@ -0,0 +1,31 @@ +.only_swift: + needs: [] + rules: + - changes: + - swift/**/* + - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+-(alpha|beta|rc)\.[0-9]+$/' + - if: '$CI_COMMIT_REF_NAME == "master"' + - if: '$CI_COMMIT_REF_NAME == "develop"' + - if: '$CI_COMMIT_REF_PROTECTED == "true"' + +.only_deploy: + rules: + - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/' + when: manual + + + +swift: + stage: bindings + needs: + - mac_os + tags: + - mac-os + script: + - cd swift/In3 + - swift build -Xlinker -L../../mac_build/lib + - swift test -Xlinker -L../../mac_build/lib + needs: [] + artifacts: + paths: + - swift/In3/.build From 8702367a4c1258d85f27b9ca4201b0aae5bb9287 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 14:30:28 +0200 Subject: [PATCH 068/221] try harder --- c/src/third-party/zkcrypto/rust/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/c/src/third-party/zkcrypto/rust/Cargo.toml b/c/src/third-party/zkcrypto/rust/Cargo.toml index 487e09602..68fd89c68 100644 --- a/c/src/third-party/zkcrypto/rust/Cargo.toml +++ b/c/src/third-party/zkcrypto/rust/Cargo.toml @@ -6,6 +6,10 @@ version = "0.1.0" authors = ["Matter Labs Team "] edition = "2018" +[net] +retry = 2 # network retries +git-fetch-with-cli = true # use the `git` executable for git operations + [lib] crate-type = ["cdylib", "rlib", "staticlib"] From 003356da8207f2b05fbdd4ea0e9e876df5bede04 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 14:33:08 +0200 Subject: [PATCH 069/221] fix requirements --- swift/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/swift/ci.yml b/swift/ci.yml index e108ceaaf..8ce3b3040 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -25,7 +25,6 @@ swift: - cd swift/In3 - swift build -Xlinker -L../../mac_build/lib - swift test -Xlinker -L../../mac_build/lib - needs: [] artifacts: paths: - swift/In3/.build From 890427c9a314dd0edfb943d717a3c5f4fa07759d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 14:44:12 +0200 Subject: [PATCH 070/221] build lib directly --- swift/ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/swift/ci.yml b/swift/ci.yml index 8ce3b3040..c3f5e166a 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -17,14 +17,15 @@ swift: stage: bindings - needs: - - mac_os tags: - mac-os script: - - cd swift/In3 - - swift build -Xlinker -L../../mac_build/lib - - swift test -Xlinker -L../../mac_build/lib + - mkdir build + - cd build + - cmake -DCMAKE_BUILD_TYPE=release -DCMD=false .. && make + - cd ../swift/In3 + - swift build -Xlinker -L../../build/lib + - swift test -Xlinker -L../../build/lib artifacts: paths: - swift/In3/.build From 46acc7222bd140d7ff0eb0cf34e7413e09bbe068 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 15:10:19 +0200 Subject: [PATCH 071/221] rename and fix CI --- swift/{In3Sys => CIn3}/Package.swift | 6 +++--- swift/{In3Sys => CIn3}/README.md | 2 +- swift/{In3Sys => CIn3}/module.modulemap | 2 +- swift/In3/Package.swift | 2 +- swift/In3/Sources/In3/In3.swift | 2 +- swift/ci.yml | 1 + 6 files changed, 8 insertions(+), 7 deletions(-) rename swift/{In3Sys => CIn3}/Package.swift (77%) rename swift/{In3Sys => CIn3}/README.md (78%) rename swift/{In3Sys => CIn3}/module.modulemap (71%) diff --git a/swift/In3Sys/Package.swift b/swift/CIn3/Package.swift similarity index 77% rename from swift/In3Sys/Package.swift rename to swift/CIn3/Package.swift index 17cde3155..c6594beef 100644 --- a/swift/In3Sys/Package.swift +++ b/swift/CIn3/Package.swift @@ -4,15 +4,15 @@ import PackageDescription let package = Package( - name: "In3Sys", + name: "CIn3", products: [ - .library(name: "In3Sys", targets: ["In3Sys"]), + .library(name: "CIn3", targets: ["CIn3"]), ], dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), ], targets: [ - .systemLibrary(name: "In3Sys"), + .systemLibrary(name: "CIn3"), ] ) diff --git a/swift/In3Sys/README.md b/swift/CIn3/README.md similarity index 78% rename from swift/In3Sys/README.md rename to swift/CIn3/README.md index 0cd1c5c51..034353072 100644 --- a/swift/In3Sys/README.md +++ b/swift/CIn3/README.md @@ -1,3 +1,3 @@ -# In3Sys +# CIn3 A description of this package. diff --git a/swift/In3Sys/module.modulemap b/swift/CIn3/module.modulemap similarity index 71% rename from swift/In3Sys/module.modulemap rename to swift/CIn3/module.modulemap index a9de6e82f..40b7eebf6 100644 --- a/swift/In3Sys/module.modulemap +++ b/swift/CIn3/module.modulemap @@ -1,4 +1,4 @@ -module In3Sys [system] { +module CIn3 [system] { header "../../c/include/in3.rs.h" link "in3" export * diff --git a/swift/In3/Package.swift b/swift/In3/Package.swift index dd6a853e2..6dafe6944 100644 --- a/swift/In3/Package.swift +++ b/swift/In3/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["In3"]), ], dependencies: [ - .package(path: "../In3Sys"), + .package(path: "../CIn3"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/swift/In3/Sources/In3/In3.swift b/swift/In3/Sources/In3/In3.swift index ef95d7d9e..468b5f0be 100644 --- a/swift/In3/Sources/In3/In3.swift +++ b/swift/In3/Sources/In3/In3.swift @@ -1,4 +1,4 @@ -import In3Sys +import CIn3 public class In3 { var in3: UnsafeMutablePointer? = nil diff --git a/swift/ci.yml b/swift/ci.yml index c3f5e166a..aefb8b94d 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -17,6 +17,7 @@ swift: stage: bindings + needs: [] tags: - mac-os script: From 21fba2724b8f44445240cc5deb881947056571c0 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 2 Apr 2021 23:52:00 +0200 Subject: [PATCH 072/221] fixed rust --- c/src/third-party/zkcrypto/rust/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/c/src/third-party/zkcrypto/rust/Cargo.toml b/c/src/third-party/zkcrypto/rust/Cargo.toml index 487e09602..68fd89c68 100644 --- a/c/src/third-party/zkcrypto/rust/Cargo.toml +++ b/c/src/third-party/zkcrypto/rust/Cargo.toml @@ -6,6 +6,10 @@ version = "0.1.0" authors = ["Matter Labs Team "] edition = "2018" +[net] +retry = 2 # network retries +git-fetch-with-cli = true # use the `git` executable for git operations + [lib] crate-type = ["cdylib", "rlib", "staticlib"] From 7832960fa67875d3e41a2e56df37c2185c44f887 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 12:32:53 +0200 Subject: [PATCH 073/221] fix some warning and refactore --- swift/CIn3/Package.swift | 18 ------------------ swift/CIn3/README.md | 3 --- swift/CIn3/module.modulemap | 5 ----- swift/In3/Package.swift | 7 +++---- swift/In3/Sources/CIn3/module.modulemap | 5 +++++ 5 files changed, 8 insertions(+), 30 deletions(-) delete mode 100644 swift/CIn3/Package.swift delete mode 100644 swift/CIn3/README.md delete mode 100644 swift/CIn3/module.modulemap create mode 100644 swift/In3/Sources/CIn3/module.modulemap diff --git a/swift/CIn3/Package.swift b/swift/CIn3/Package.swift deleted file mode 100644 index c6594beef..000000000 --- a/swift/CIn3/Package.swift +++ /dev/null @@ -1,18 +0,0 @@ -// swift-tools-version:5.3 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "CIn3", - products: [ - .library(name: "CIn3", targets: ["CIn3"]), - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ], - targets: [ - .systemLibrary(name: "CIn3"), - ] -) diff --git a/swift/CIn3/README.md b/swift/CIn3/README.md deleted file mode 100644 index 034353072..000000000 --- a/swift/CIn3/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# CIn3 - -A description of this package. diff --git a/swift/CIn3/module.modulemap b/swift/CIn3/module.modulemap deleted file mode 100644 index 40b7eebf6..000000000 --- a/swift/CIn3/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module CIn3 [system] { - header "../../c/include/in3.rs.h" - link "in3" - export * -} diff --git a/swift/In3/Package.swift b/swift/In3/Package.swift index 6dafe6944..f5543c33a 100644 --- a/swift/In3/Package.swift +++ b/swift/In3/Package.swift @@ -11,15 +11,14 @@ let package = Package( name: "In3", targets: ["In3"]), ], - dependencies: [ - .package(path: "../CIn3"), - ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. + .systemLibrary( + name: "CIn3"), .target( name: "In3", - dependencies: []), + dependencies: ["CIn3"]), .testTarget( name: "In3Tests", dependencies: ["In3"]), diff --git a/swift/In3/Sources/CIn3/module.modulemap b/swift/In3/Sources/CIn3/module.modulemap new file mode 100644 index 000000000..2c02919f4 --- /dev/null +++ b/swift/In3/Sources/CIn3/module.modulemap @@ -0,0 +1,5 @@ +module CIn3 [system] { + umbrella header "../../../../c/include/in3.rs.h" + link "in3" + export * +} From eb57cee9ef0266afba8a57bfc0e7f8a9cf78c92e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 12:35:45 +0200 Subject: [PATCH 074/221] moved paths --- swift/In3/Sources/CIn3/module.modulemap | 5 ----- swift/{In3 => }/Package.swift | 0 swift/{In3 => }/README.md | 0 swift/Sources/CIn3/module.modulemap | 5 +++++ swift/{In3 => }/Sources/In3/In3.swift | 0 swift/{In3 => }/Tests/In3Tests/In3Tests.swift | 0 swift/{In3 => }/Tests/In3Tests/XCTestManifests.swift | 0 swift/{In3 => }/Tests/LinuxMain.swift | 0 8 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 swift/In3/Sources/CIn3/module.modulemap rename swift/{In3 => }/Package.swift (100%) rename swift/{In3 => }/README.md (100%) create mode 100644 swift/Sources/CIn3/module.modulemap rename swift/{In3 => }/Sources/In3/In3.swift (100%) rename swift/{In3 => }/Tests/In3Tests/In3Tests.swift (100%) rename swift/{In3 => }/Tests/In3Tests/XCTestManifests.swift (100%) rename swift/{In3 => }/Tests/LinuxMain.swift (100%) diff --git a/swift/In3/Sources/CIn3/module.modulemap b/swift/In3/Sources/CIn3/module.modulemap deleted file mode 100644 index 2c02919f4..000000000 --- a/swift/In3/Sources/CIn3/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module CIn3 [system] { - umbrella header "../../../../c/include/in3.rs.h" - link "in3" - export * -} diff --git a/swift/In3/Package.swift b/swift/Package.swift similarity index 100% rename from swift/In3/Package.swift rename to swift/Package.swift diff --git a/swift/In3/README.md b/swift/README.md similarity index 100% rename from swift/In3/README.md rename to swift/README.md diff --git a/swift/Sources/CIn3/module.modulemap b/swift/Sources/CIn3/module.modulemap new file mode 100644 index 000000000..827c5a4cb --- /dev/null +++ b/swift/Sources/CIn3/module.modulemap @@ -0,0 +1,5 @@ +module CIn3 [system] { + umbrella header "../../../c/include/in3.rs.h" + link "in3" + export * +} diff --git a/swift/In3/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift similarity index 100% rename from swift/In3/Sources/In3/In3.swift rename to swift/Sources/In3/In3.swift diff --git a/swift/In3/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift similarity index 100% rename from swift/In3/Tests/In3Tests/In3Tests.swift rename to swift/Tests/In3Tests/In3Tests.swift diff --git a/swift/In3/Tests/In3Tests/XCTestManifests.swift b/swift/Tests/In3Tests/XCTestManifests.swift similarity index 100% rename from swift/In3/Tests/In3Tests/XCTestManifests.swift rename to swift/Tests/In3Tests/XCTestManifests.swift diff --git a/swift/In3/Tests/LinuxMain.swift b/swift/Tests/LinuxMain.swift similarity index 100% rename from swift/In3/Tests/LinuxMain.swift rename to swift/Tests/LinuxMain.swift From 7ea6de8c378626f43710dbbd12deab6e5ef47f5e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 13:04:10 +0200 Subject: [PATCH 075/221] fix macos-version --- swift/Package.swift | 3 +++ swift/ci.yml | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/swift/Package.swift b/swift/Package.swift index f5543c33a..a432c84d8 100644 --- a/swift/Package.swift +++ b/swift/Package.swift @@ -5,6 +5,9 @@ import PackageDescription let package = Package( name: "In3", + platforms: [ + .macOS(.v10_15), + ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( diff --git a/swift/ci.yml b/swift/ci.yml index aefb8b94d..67626b2fb 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -23,10 +23,10 @@ swift: script: - mkdir build - cd build - - cmake -DCMAKE_BUILD_TYPE=release -DCMD=false .. && make - - cd ../swift/In3 - - swift build -Xlinker -L../../build/lib - - swift test -Xlinker -L../../build/lib + - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DTRANSPORTS=false -DUSE_CURL=false -DCMD=false .. && make && rm -f lib/libin3.dylib + - cd ../swift + - swift build -Xlinker -L../build/lib + - swift test -Xlinker -L../build/lib artifacts: paths: - - swift/In3/.build + - swift/.build From 9a64cfeb3aad361e7dd45f132a24545e5c601dbc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 13:23:52 +0200 Subject: [PATCH 076/221] allow index arguments --- swift/Sources/In3/In3.swift | 4 ++-- swift/Tests/In3Tests/In3Tests.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 468b5f0be..853f16ae0 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -13,7 +13,7 @@ public class In3 { return result } - public init(config: String) { + public init(_ config: String) { in3 = in3_for_chain_auto_init(1) in3_configure(in3, config) } @@ -22,7 +22,7 @@ public class In3 { in3_free(in3) } - public func execute(rpc: String) -> String { + public func execute(_ rpc: String) -> String { return String(cString: in3_client_exec_req(in3, makeCString(from: rpc))) } } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index d852d16c1..9651abd09 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -3,8 +3,8 @@ import XCTest final class In3Tests: XCTestCase { func testExample() { - let in3 = In3(config: "{\"chainId\":\"mainnet\"}") - let res = in3.execute(rpc: "{\"method\":\"keccak\",\"params\":[\"simon\"]}") + let in3 = In3( "{\"chainId\":\"mainnet\"}") + let res = in3.execute("{\"method\":\"keccak\",\"params\":[\"simon\"]}") // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct // results. From e46258df6d9896e4da0e35af26a86e8c3e4218b4 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 13:39:01 +0200 Subject: [PATCH 077/221] added throwong errors in config --- swift/Sources/In3/In3.swift | 13 +++++++++++-- swift/Tests/In3Tests/In3Tests.swift | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 853f16ae0..fedbfc40d 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -1,5 +1,11 @@ import CIn3 +enum IncubedError: Error { + case config(message: String) + case rpc(message: String) +} + + public class In3 { var in3: UnsafeMutablePointer? = nil @@ -13,9 +19,12 @@ public class In3 { return result } - public init(_ config: String) { + public init(_ config: String) throws { in3 = in3_for_chain_auto_init(1) - in3_configure(in3, config) + let error = in3_configure(in3, config) + if let msg = error { + throw IncubedError.config(message: String(cString: msg)) + } } deinit { diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 9651abd09..30d690f83 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -2,8 +2,8 @@ import XCTest @testable import In3 final class In3Tests: XCTestCase { - func testExample() { - let in3 = In3( "{\"chainId\":\"mainnet\"}") + func testExample() throws { + let in3 = try In3( "{\"chainId\":\"mainnet\"}") let res = in3.execute("{\"method\":\"keccak\",\"params\":[\"simon\"]}") // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct From d0c405db4457782f1ed5f87d0b99d4078865dfba Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 18:23:23 +0200 Subject: [PATCH 078/221] add RPC --- swift/Sources/In3/In3.swift | 24 +- swift/Sources/In3/Utils/JsonRpc.swift | 334 ++++++++++++++++++++++++++ swift/Tests/In3Tests/In3Tests.swift | 8 + 3 files changed, 364 insertions(+), 2 deletions(-) create mode 100644 swift/Sources/In3/Utils/JsonRpc.swift diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index fedbfc40d..587732548 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -1,4 +1,5 @@ import CIn3 +import Foundation enum IncubedError: Error { case config(message: String) @@ -21,14 +22,33 @@ public class In3 { public init(_ config: String) throws { in3 = in3_for_chain_auto_init(1) + try configure(config) + } + + deinit { + in3_free(in3) + } + + public func configure(_ config: String) throws { let error = in3_configure(in3, config) if let msg = error { throw IncubedError.config(message: String(cString: msg)) } } - deinit { - in3_free(in3) + public func execLocal(_ method: String, _ params: RPCObject) throws -> RPCObject { + let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(params))) + let rawResult = execute(String(decoding: jsonReqData, as: UTF8.self)) + let response = try JSONDecoder().decode(JSONResponse.self, from: rawResult.data(using: .utf8)!) + if let error = response.error { + throw IncubedError.rpc(message: error.message) + } + else if let result = response.result { + return RPCObject(result) + } + else { + throw IncubedError.rpc(message: "No Result in response") + } } public func execute(_ rpc: String) -> String { diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift new file mode 100644 index 000000000..394a752a2 --- /dev/null +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -0,0 +1,334 @@ +import Foundation + +/* + spec from https://www.jsonrpc.org/specification + ----------------------------------------------- + Request object + A rpc call is represented by sending a Request object to a Server. The Request object has the following members: + jsonrpc + A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0". + method + A String containing the name of the method to be invoked. Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and MUST NOT be used for anything else. + params + A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted. + id + An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2] + The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. + [1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling. + [2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions. + 4.1 Notification + A Notification is a Request object without an "id" member. A Request object that is a Notification signifies the Client's lack of interest in the corresponding Response object, and as such no Response object needs to be returned to the client. The Server MUST NOT reply to a Notification, including those that are within a batch request. + Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params","Internal error"). + 4.2 Parameter Structures + If present, parameters for the rpc call MUST be provided as a Structured value. Either by-position through an Array or by-name through an Object. + by-position: params MUST be an Array, containing the values in the Server expected order. + by-name: params MUST be an Object, with member names that match the Server expected parameter names. The absence of expected names MAY result in an error being generated. The names MUST match exactly, including case, to the method's expected parameters. + Response object + When a rpc call is made, the Server MUST reply with a Response, except for in the case of Notifications. The Response is expressed as a single JSON Object, with the following members: + jsonrpc + A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0". + result + This member is REQUIRED on success. + This member MUST NOT exist if there was an error invoking the method. + The value of this member is determined by the method invoked on the Server. + error + This member is REQUIRED on error. + This member MUST NOT exist if there was no error triggered during invocation. + The value for this member MUST be an Object as defined in section 5.1. + id + This member is REQUIRED. + It MUST be the same as the value of the id member in the Request Object. + If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be Null. + Either the result member or error member MUST be included, but both members MUST NOT be included. + 5.1 Error object + When a rpc call encounters an error, the Response Object MUST contain the error member with a value that is a Object with the following members: + code + A Number that indicates the error type that occurred. + This MUST be an integer. + message + A String providing a short description of the error. + The message SHOULD be limited to a concise single sentence. + data + A Primitive or Structured value that contains additional information about the error. + This may be omitted. + The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.). + The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php + code message meaning + -32700 Parse error Invalid JSON was received by the server. + An error occurred on the server while parsing the JSON text. + -32600 Invalid Request The JSON sent is not a valid Request object. + -32601 Method not found The method does not exist / is not available. + -32602 Invalid params Invalid method parameter(s). + -32603 Internal error Internal JSON-RPC error. + -32000 to -32099 Server error Reserved for implementation-defined server-errors. + */ + +private let jsonrpcVersion = "2.0" + +internal struct JSONRequest: Codable { + var jsonrpc: String + var id: Int + var method: String + var params: JSONObject + + init(id: Int, method: String, params: JSONObject) { + self.jsonrpc = jsonrpcVersion + self.id = id + self.method = method + self.params = params + } +} + +internal struct JSONResponse: Codable { + var jsonrpc: String + var id: Int + var result: JSONObject? + var error: JSONError? + + init(id: Int, result: JSONObject) { + self.jsonrpc = jsonrpcVersion + self.id = id + self.result = result + self.error = nil + } + + init(id: Int, error: JSONError) { + self.jsonrpc = jsonrpcVersion + self.id = id + self.result = nil + self.error = error + } + + init(id: Int, errorCode: JSONErrorCode, error: Error) { + self.init(id: id, error: JSONError(code: errorCode, error: error)) + } + + init(id: Int, result: RPCObject) { + self.init(id: id, result: JSONObject(result)) + } + + init(id: Int, error: RPCError) { + self.init(id: id, error: JSONError(error)) + } +} + +internal struct JSONError: Codable { + var code: Int + var message: String + var data: Dictionary? + + init(code: Int, message: String) { + self.code = code + self.message = message + self.data = nil + } + + init(code: JSONErrorCode, message: String) { + self.init(code: code.rawValue, message: message) + } + + init(code: JSONErrorCode, error: Error) { + self.init(code: code, message: String(describing: error)) + } + + init(_ error: RPCError) { + switch error.kind { + case .invalidMethod: + self.init(code: .methodNotFound, message: error.description ?? "invalid method") + case .invalidParams: + self.init(code: .invalidParams, message: error.description ?? "invalid params") + case .invalidRequest: + self.init(code: .invalidRequest, message: error.description ?? "invalid request") + case .applicationError(let description): + self.init(code: .other, message: error.description ?? description) + } + } +} + +internal enum JSONErrorCode: Int, Codable { + case parseError = -32700 + case invalidRequest = -32600 + case methodNotFound = -32601 + case invalidParams = -32602 + case internalError = -32603 + case other = -32000 +} + +internal enum JSONObject: Codable { + case none + case string(String) + case integer(Int) + case double(Double) + case bool(Bool) + case list([JSONObject]) + case dictionary([String: JSONObject]) + + init(_ object: RPCObject) { + switch object { + case .none: + self = .none + case .string(let value): + self = .string(value) + case .integer(let value): + self = .integer(value) + case .double(let value): + self = .double(value) + case .bool(let value): + self = .bool(value) + case .list(let value): + self = .list(value.map { JSONObject($0) }) + case .dictionary(let value): + self = .dictionary(value.mapValues { JSONObject($0) }) + } + } +} + +internal extension JSONObject { + enum CodingKeys: CodingKey { + case string + case integer + case double + case bool + case list + case dictionary + } + + // FIXME: is there a more elegant way? + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + do { + let value = try container.decode(String.self) + self = .string(value) + } catch { + do { + let value = try container.decode(Int.self) + self = .integer(value) + } catch { + do { + let value = try container.decode(Double.self) + self = .double(value) + } catch { + do { + let value = try container.decode(Bool.self) + self = .bool(value) + } catch { + do { + let value = try container.decode([JSONObject].self) + self = .list(value) + } catch { + do { + let value = try container.decode([String: JSONObject].self) + self = .dictionary(value) + } catch { + self = .none + } + } + } + } + } + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .none: + break + case .string(let value): + try container.encode(value) + case .integer(let value): + try container.encode(value) + case .double(let value): + try container.encode(value) + case .bool(let value): + try container.encode(value) + case .list(let value): + try container.encode(value) + case .dictionary(let value): + try container.encode(value) + } + } +} + +public enum RPCObject: Equatable { + case none + case string(String) + case integer(Int) + case double(Double) + case bool(Bool) + case list([RPCObject]) + case dictionary([String: RPCObject]) + + public init(_ value: String) { + self = .string(value) + } + + public init(_ value: Int) { + self = .integer(value) + } + + public init(_ value: Double) { + self = .double(value) + } + + public init(_ value: Bool) { + self = .bool(value) + } + + public init(_ value: [String]) { + self = .list(value.map { RPCObject($0) }) + } + + public init(_ value: [Int]) { + self = .list(value.map { RPCObject($0) }) + } + + public init(_ value: [String: String]) { + self = .dictionary(value.mapValues { RPCObject($0) }) + } + + public init(_ value: [String: Int]) { + self = .dictionary(value.mapValues { RPCObject($0) }) + } + + public init(_ value: [RPCObject]) { + self = .list(value) + } + + internal init(_ object: JSONObject) { + switch object { + case .none: + self = .none + case .string(let value): + self = .string(value) + case .integer(let value): + self = .integer(value) + case .double(let value): + self = .double(value) + case .bool(let value): + self = .bool(value) + case .list(let value): + self = .list(value.map { RPCObject($0) }) + case .dictionary(let value): + self = .dictionary(value.mapValues { RPCObject($0) }) + } + } +} + +public struct RPCError { + public init(_ kind: Kind, description: String? = nil) { + self.kind = kind + self.description = description + } + + public let kind: Kind + public let description: String? + + public enum Kind { + case invalidMethod + case invalidParams(String) + case invalidRequest(String) + case applicationError(String) + } +} + diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 30d690f83..bbbc9083c 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -4,6 +4,14 @@ import XCTest final class In3Tests: XCTestCase { func testExample() throws { let in3 = try In3( "{\"chainId\":\"mainnet\"}") + let hash = try in3.execLocal("keccak",RPCObject(["simon"])) + switch hash { + case let .string(value): + XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") + default: + XCTAssertTrue(false, "Invalid return type") + } + let res = in3.execute("{\"method\":\"keccak\",\"params\":[\"simon\"]}") // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct From 44e99dac25d9d22dc897bd66734c95dda8a48ff8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 18:25:49 +0200 Subject: [PATCH 079/221] optimize --- c/src/third-party/zkcrypto/rust/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/c/src/third-party/zkcrypto/rust/Cargo.toml b/c/src/third-party/zkcrypto/rust/Cargo.toml index 68fd89c68..76ed13a46 100644 --- a/c/src/third-party/zkcrypto/rust/Cargo.toml +++ b/c/src/third-party/zkcrypto/rust/Cargo.toml @@ -44,5 +44,4 @@ wasm-bindgen-test = "0.3.10" byteorder = "1.3.4" [profile.release] -# Tell `rustc` to optimize for small code size. opt-level = "s" From d3d9124e6db40d299b1de034dc187d9dd8e5a03e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 19:15:46 +0200 Subject: [PATCH 080/221] make internal --- .gitignore | 1 + swift/Sources/In3/In3.swift | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 32c669d10..cb5a6ac5e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ cmake-build-debug/ .idea/ .settings/ # Vim +swift/.swiftpm/ python/htmlcov wasm/test/.nyc_output wasm/test/coverage diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 587732548..a8da06ae3 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -10,11 +10,10 @@ enum IncubedError: Error { public class In3 { var in3: UnsafeMutablePointer? = nil - func makeCString(from str: String) -> UnsafeMutablePointer { + internal func makeCString(from str: String) -> UnsafeMutablePointer { let count = str.utf8.count + 1 let result = UnsafeMutablePointer.allocate(capacity: count) str.withCString { (baseAddress) in - // func initialize(from: UnsafePointer, count: Int) result.initialize(from: baseAddress, count: count) } return result From 83e92a565d2eaac6bf45ada0d5c77957f2647707 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 3 Apr 2021 23:24:29 +0200 Subject: [PATCH 081/221] use varargs --- swift/Sources/In3/In3.swift | 4 ++-- swift/Tests/In3Tests/In3Tests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index a8da06ae3..3c581868e 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -35,8 +35,8 @@ public class In3 { } } - public func execLocal(_ method: String, _ params: RPCObject) throws -> RPCObject { - let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(params))) + public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { + let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))) let rawResult = execute(String(decoding: jsonReqData, as: UTF8.self)) let response = try JSONDecoder().decode(JSONResponse.self, from: rawResult.data(using: .utf8)!) if let error = response.error { diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index bbbc9083c..91c17d56a 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -4,7 +4,7 @@ import XCTest final class In3Tests: XCTestCase { func testExample() throws { let in3 = try In3( "{\"chainId\":\"mainnet\"}") - let hash = try in3.execLocal("keccak",RPCObject(["simon"])) + let hash = try in3.execLocal("keccak",RPCObject("simon")) switch hash { case let .string(value): XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") From 959775921693162173bee8eaa7b3ee7820dcedce Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 00:19:20 +0200 Subject: [PATCH 082/221] add transport --- swift/Sources/In3/In3.swift | 7 ++----- swift/Sources/In3/Utils/Error.swift | 11 +++++++++++ swift/Sources/In3/Utils/Transport.swift | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 swift/Sources/In3/Utils/Error.swift create mode 100644 swift/Sources/In3/Utils/Transport.swift diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 3c581868e..f7d1bc2a7 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -1,14 +1,10 @@ import CIn3 import Foundation -enum IncubedError: Error { - case config(message: String) - case rpc(message: String) -} - public class In3 { var in3: UnsafeMutablePointer? = nil + var transport: (_ url: String, _ method:String, _ payload:Data, _ headers: [String], _ cb:(_ data:TransportResult)->Void) -> Void internal func makeCString(from str: String) -> UnsafeMutablePointer { let count = str.utf8.count + 1 @@ -20,6 +16,7 @@ public class In3 { } public init(_ config: String) throws { + transport = httpTransfer in3 = in3_for_chain_auto_init(1) try configure(config) } diff --git a/swift/Sources/In3/Utils/Error.swift b/swift/Sources/In3/Utils/Error.swift new file mode 100644 index 000000000..c7e8e9b0b --- /dev/null +++ b/swift/Sources/In3/Utils/Error.swift @@ -0,0 +1,11 @@ +import Foundation + +enum IncubedError: Error { + case config(message: String) + case rpc(message: String) +} + +enum TransportResult { + case success(_ data:Data, _ time:Int) + case error(_ msg:String, _ httpStatus:Int) +} \ No newline at end of file diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift new file mode 100644 index 000000000..bf62a31d1 --- /dev/null +++ b/swift/Sources/In3/Utils/Transport.swift @@ -0,0 +1,5 @@ +import Foundation + +func httpTransfer(_ url: String, _ method:String, _ payload:Data, _ headers: [String], cb:(_ data:TransportResult)->Void) { + cb(TransportResult.error("Not implemented",-7)) +} From a8706cd05df6a95f4bbe73d5b0f4713e08cb245b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 18:37:44 +0200 Subject: [PATCH 083/221] added async request --- c/include/in3/request.h | 5 + c/src/core/client/request.c | 7 ++ c/src/core/client/request.h | 5 + swift/Sources/In3/In3.swift | 20 ++-- swift/Sources/In3/Utils/Error.swift | 11 ++- swift/Sources/In3/Utils/Transport.swift | 120 +++++++++++++++++++++++- swift/Sources/In3/Utils/Utils.swift | 8 ++ 7 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 swift/Sources/In3/Utils/Utils.swift diff --git a/c/include/in3/request.h b/c/include/in3/request.h index 7b97f557a..880491aaf 100644 --- a/c/include/in3/request.h +++ b/c/include/in3/request.h @@ -312,6 +312,11 @@ char* req_get_response_data( in3_req_t* req /**< [in] the request context. */ ); +/** + * returns the result or NULL in case of an error for that context. The result must be freed! + */ +char* req_get_result_json(in3_req_t* ctx, int index); + /** * returns the type of the request */ diff --git a/c/src/core/client/request.c b/c/src/core/client/request.c index 74f063c77..01199a878 100644 --- a/c/src/core/client/request.c +++ b/c/src/core/client/request.c @@ -109,6 +109,13 @@ char* req_get_error_data(in3_req_t* ctx) { return ctx ? ctx->error : "No request context"; } +char* req_get_result_json(in3_req_t* ctx, int index) { + assert_in3_req(ctx); + if (!ctx->responses) return NULL; + d_token_t* res = d_get(ctx->responses[index], K_RESULT); + return res ? d_create_json(ctx->response_context, res) : NULL; +} + char* req_get_response_data(in3_req_t* ctx) { assert_in3_req(ctx); diff --git a/c/src/core/client/request.h b/c/src/core/client/request.h index 90f23adb0..c1899a287 100644 --- a/c/src/core/client/request.h +++ b/c/src/core/client/request.h @@ -312,6 +312,11 @@ char* req_get_response_data( in3_req_t* req /**< [in] the request context. */ ); +/** + * returns the result or NULL in case of an error for that context. The result must be freed! + */ +char* req_get_result_json(in3_req_t* ctx, int index); + /** * returns the type of the request */ diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index f7d1bc2a7..94df2d69a 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -3,17 +3,9 @@ import Foundation public class In3 { - var in3: UnsafeMutablePointer? = nil - var transport: (_ url: String, _ method:String, _ payload:Data, _ headers: [String], _ cb:(_ data:TransportResult)->Void) -> Void - - internal func makeCString(from str: String) -> UnsafeMutablePointer { - let count = str.utf8.count + 1 - let result = UnsafeMutablePointer.allocate(capacity: count) - str.withCString { (baseAddress) in - result.initialize(from: baseAddress, count: count) - } - return result - } + internal var in3: UnsafeMutablePointer? = nil + public var transport: (_ url: String, _ method:String, _ payload:Data, _ headers: [String], _ cb:(_ data:TransportResult)->Void) -> Void + public init(_ config: String) throws { transport = httpTransfer @@ -32,6 +24,8 @@ public class In3 { } } + /// Execute a request directly and local. + /// This works only for requests which do not need to be send to a server. public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))) let rawResult = execute(String(decoding: jsonReqData, as: UTF8.self)) @@ -47,6 +41,10 @@ public class In3 { } } + public func exec(_ method: String, _ params: RPCObject..., cb: @escaping (_ result:RequestResult)->Void) throws { + try In3Request(method,params,self,cb).exec() + } + public func execute(_ rpc: String) -> String { return String(cString: in3_client_exec_req(in3, makeCString(from: rpc))) } diff --git a/swift/Sources/In3/Utils/Error.swift b/swift/Sources/In3/Utils/Error.swift index c7e8e9b0b..add61c347 100644 --- a/swift/Sources/In3/Utils/Error.swift +++ b/swift/Sources/In3/Utils/Error.swift @@ -1,11 +1,16 @@ import Foundation -enum IncubedError: Error { +public enum IncubedError: Error { case config(message: String) case rpc(message: String) } -enum TransportResult { +public enum TransportResult { case success(_ data:Data, _ time:Int) case error(_ msg:String, _ httpStatus:Int) -} \ No newline at end of file +} + +public enum RequestResult { + case success(_ data:RPCObject) + case error(_ msg:String) +} diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index bf62a31d1..8340f99a7 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -1,5 +1,123 @@ import Foundation +import CIn3 -func httpTransfer(_ url: String, _ method:String, _ payload:Data, _ headers: [String], cb:(_ data:TransportResult)->Void) { +internal func httpTransfer(_ url: String, _ method:String, _ payload:Data, _ headers: [String], cb:(_ data:TransportResult)->Void) { cb(TransportResult.error("Not implemented",-7)) } + + +internal class In3Request { + var req:UnsafeMutablePointer + var in3:In3 + var cb: (_ result:RequestResult)->Void + + init(_ method: String, _ params: [RPCObject],_ _in3:In3, _ _cb: @escaping (_ result:RequestResult)->Void) throws { + let r = req_new(_in3.in3, String(decoding: try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))), as: UTF8.self)) + if let r = r { + req = r + } + else { + throw IncubedError.rpc(message: "Invalid JSON") + } + in3 = _in3 + cb = _cb + } + + deinit { + req_free(req) + } + + func reportError(req:UnsafeMutablePointer) { + if let error = req.pointee.error { + DispatchQueue.main.async { + self.cb(RequestResult.error(String(cString: error))) + } + } + else if let required = req.pointee.required { + reportError(req: required) + } + else { + DispatchQueue.main.async { + self.cb(RequestResult.error("Unknown Error")) + } + } + } + + func exec() { + switch in3_req_exec_state(req) { + case REQ_SUCCESS : + let result = req_get_result_json(req,0) + if let res = result { + let resultString = String(cString: res) + do { + let response = try JSONDecoder().decode(JSONObject.self, from: resultString.data(using: .utf8)!) + DispatchQueue.main.async { + self.cb(RequestResult.success(RPCObject(response))) + } + } catch { + DispatchQueue.main.async { + self.cb(RequestResult.error( "Error parsing the result '\(resultString)' : \(error)")) + } + } + } + _free_(result) + case REQ_ERROR : + reportError(req: req) + + case REQ_WAITING_TO_SEND: + // create request + let http_req = in3_create_request(req) + guard let http = http_req else { + reportError(req: req) + return + } + for i in 0.. Void in + switch res { + case let .success(data, time): + let ptr = data.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } + if let p = ptr { + in3_req_add_response(http,Int32(i),0,p,Int32(data.count), UInt32(time)) + } + case let .error(msg,httpStatus): + let ptr = msg.data(using: .utf8)!.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } + if let p = ptr { + in3_req_add_response(http,Int32(i),Int32(-httpStatus),p,Int32(-1), UInt32(0)) + } + } + self.exec() + } + + + // do we need before sending the request? + if http.pointee.wait > 0 { + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Int(http.pointee.wait)) ) { + self.sendHttp(http: http, index:i, cb:cbResult) + } + } else { + self.sendHttp(http: http, index:i, cb: cbResult) + } + } + + case REQ_WAITING_FOR_RESPONSE: + // create request + // for i=0 i< urls_len + // send it with callbacks + // in3.transport + DispatchQueue.main.async { + self.cb(RequestResult.error( "not implemented yet :")) + } + default: + DispatchQueue.main.async { + self.cb(RequestResult.error( "not expected")) + } + } + } + + func sendHttp(http:UnsafeMutablePointer, index:Int, cb:(_ data:TransportResult)->Void) { + + + } + + +} diff --git a/swift/Sources/In3/Utils/Utils.swift b/swift/Sources/In3/Utils/Utils.swift new file mode 100644 index 000000000..6392b0087 --- /dev/null +++ b/swift/Sources/In3/Utils/Utils.swift @@ -0,0 +1,8 @@ + internal func makeCString(from str: String) -> UnsafeMutablePointer { + let count = str.utf8.count + 1 + let result = UnsafeMutablePointer.allocate(capacity: count) + str.withCString { (baseAddress) in + result.initialize(from: baseAddress, count: count) + } + return result + } From 81a153040107e57fb86ab241b79d863de24a0cce Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 20:04:28 +0200 Subject: [PATCH 084/221] fix sendHttp --- swift/Sources/In3/Utils/Transport.swift | 74 ++++++++++++++++++++----- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index 8340f99a7..e952ae244 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -10,6 +10,7 @@ internal class In3Request { var req:UnsafeMutablePointer var in3:In3 var cb: (_ result:RequestResult)->Void + var freed: Bool init(_ method: String, _ params: [RPCObject],_ _in3:In3, _ _cb: @escaping (_ result:RequestResult)->Void) throws { let r = req_new(_in3.in3, String(decoding: try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))), as: UTF8.self)) @@ -21,10 +22,18 @@ internal class In3Request { } in3 = _in3 cb = _cb + freed = false + } + + func free() { + if !freed { + freed = true + req_free(req) + } } deinit { - req_free(req) + self.free() } func reportError(req:UnsafeMutablePointer) { @@ -32,6 +41,7 @@ internal class In3Request { DispatchQueue.main.async { self.cb(RequestResult.error(String(cString: error))) } + self.free() } else if let required = req.pointee.required { reportError(req: required) @@ -40,6 +50,7 @@ internal class In3Request { DispatchQueue.main.async { self.cb(RequestResult.error("Unknown Error")) } + self.free() } } @@ -59,11 +70,19 @@ internal class In3Request { self.cb(RequestResult.error( "Error parsing the result '\(resultString)' : \(error)")) } } + } else { + DispatchQueue.main.async { + self.cb(RequestResult.error( "The response was null")) + } } + _free_(result) + self.free() + case REQ_ERROR : reportError(req: req) + case REQ_WAITING_TO_SEND: // create request let http_req = in3_create_request(req) @@ -71,25 +90,37 @@ internal class In3Request { reportError(req: req) return } + let req_ptr = http.pointee.req + guard let req = req_ptr else { + reportError(req: self.req) + return + } + for i in 0.. Void in + let cbResult = {(_ res:TransportResult) -> Void in + // in case the response is not needed, we simply discard it. + if self.freed || in3_req_state(req) != REQ_WAITING_FOR_RESPONSE { + return + } + + // set the response... switch res { case let .success(data, time): let ptr = data.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } if let p = ptr { - in3_req_add_response(http,Int32(i),0,p,Int32(data.count), UInt32(time)) + in3_ctx_add_response(req,Int32(i),0,p,Int32(data.count), UInt32(time)) } case let .error(msg,httpStatus): let ptr = msg.data(using: .utf8)!.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } if let p = ptr { - in3_req_add_response(http,Int32(i),Int32(-httpStatus),p,Int32(-1), UInt32(0)) + in3_ctx_add_response(req,Int32(i),Int32(-httpStatus),p,Int32(-1), UInt32(0)) } } + // now try to verify the response self.exec() } - - // do we need before sending the request? + // do we need to wait before sending the request? if http.pointee.wait > 0 { DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Int(http.pointee.wait)) ) { self.sendHttp(http: http, index:i, cb:cbResult) @@ -100,13 +131,8 @@ internal class In3Request { } case REQ_WAITING_FOR_RESPONSE: - // create request - // for i=0 i< urls_len - // send it with callbacks - // in3.transport - DispatchQueue.main.async { - self.cb(RequestResult.error( "not implemented yet :")) - } + // here we do nothing, but simply wait for the next event + return default: DispatchQueue.main.async { self.cb(RequestResult.error( "not expected")) @@ -114,9 +140,27 @@ internal class In3Request { } } - func sendHttp(http:UnsafeMutablePointer, index:Int, cb:(_ data:TransportResult)->Void) { - + func sendHttp(http:UnsafeMutablePointer, index:Int, cb:@escaping (_ data:TransportResult)->Void) { + let payload = Data(buffer:UnsafeMutableBufferPointer(start: http.pointee.payload, count: Int(http.pointee.payload_len))) + var headers:[String] = [] + var p = http.pointee.headers + let url = http.pointee.urls + index + while let ph = p { + headers.append(String(cString: ph.pointee.value)) + p = ph.pointee.next + } + if let url = url.pointee { + in3.transport( String(cString:url) , String(cString: http.pointee.method), payload, headers, cb) + } else { + DispatchQueue.main.async { + cb(TransportResult.error("No URL specified",500)) + } + } + // if this was the last request we sent out, we clean up the request. + if index == http.pointee.urls_len - 1 { + request_free(http) + } } From 728ad70109e6007bcbb8b43051fe48ac15ad2b3b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 20:24:06 +0200 Subject: [PATCH 085/221] cleanup and refactore --- swift/Sources/In3/In3.swift | 13 ++++++++++--- swift/Sources/In3/Utils/JsonRpc.swift | 4 ++++ swift/Sources/In3/Utils/Utils.swift | 8 -------- swift/Tests/In3Tests/In3Tests.swift | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) delete mode 100644 swift/Sources/In3/Utils/Utils.swift diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 94df2d69a..14a9bc6c7 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -28,7 +28,7 @@ public class In3 { /// This works only for requests which do not need to be send to a server. public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))) - let rawResult = execute(String(decoding: jsonReqData, as: UTF8.self)) + let rawResult = executeJSON(String(decoding: jsonReqData, as: UTF8.self)) let response = try JSONDecoder().decode(JSONResponse.self, from: rawResult.data(using: .utf8)!) if let error = response.error { throw IncubedError.rpc(message: error.message) @@ -45,8 +45,15 @@ public class In3 { try In3Request(method,params,self,cb).exec() } - public func execute(_ rpc: String) -> String { - return String(cString: in3_client_exec_req(in3, makeCString(from: rpc))) + public func executeJSON(_ rpc: String) -> String { + return rpc.withCString { (baseAddress)->String in + let count = rpc.utf8.count + 1 + let cstr = UnsafeMutablePointer.allocate(capacity: count) + cstr.initialize(from: baseAddress, count: count) + let result = String(cString: in3_client_exec_req(in3, cstr)) + cstr.deallocate() + return result + } } } diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index 394a752a2..c406d4992 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -291,6 +291,10 @@ public enum RPCObject: Equatable { self = .dictionary(value.mapValues { RPCObject($0) }) } + public init(_ value: [String: RPCObject]) { + self = .dictionary(value) + } + public init(_ value: [RPCObject]) { self = .list(value) } diff --git a/swift/Sources/In3/Utils/Utils.swift b/swift/Sources/In3/Utils/Utils.swift deleted file mode 100644 index 6392b0087..000000000 --- a/swift/Sources/In3/Utils/Utils.swift +++ /dev/null @@ -1,8 +0,0 @@ - internal func makeCString(from str: String) -> UnsafeMutablePointer { - let count = str.utf8.count + 1 - let result = UnsafeMutablePointer.allocate(capacity: count) - str.withCString { (baseAddress) in - result.initialize(from: baseAddress, count: count) - } - return result - } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 91c17d56a..a8be47e4e 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -12,7 +12,7 @@ final class In3Tests: XCTestCase { XCTAssertTrue(false, "Invalid return type") } - let res = in3.execute("{\"method\":\"keccak\",\"params\":[\"simon\"]}") + let res = in3.executeJSON("{\"method\":\"keccak\",\"params\":[\"simon\"]}") // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct // results. From 4ac79c593a09e68f28f76ef64107b5c1cab90bc5 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 21:26:44 +0200 Subject: [PATCH 086/221] cleanup and refactore --- swift/Sources/In3/In3.swift | 7 +++--- swift/Tests/In3Tests/In3Tests.swift | 36 ++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 14a9bc6c7..87cd59964 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -49,10 +49,11 @@ public class In3 { return rpc.withCString { (baseAddress)->String in let count = rpc.utf8.count + 1 let cstr = UnsafeMutablePointer.allocate(capacity: count) + defer { + cstr.deallocate() + } cstr.initialize(from: baseAddress, count: count) - let result = String(cString: in3_client_exec_req(in3, cstr)) - cstr.deallocate() - return result + return String(cString: in3_client_exec_req(in3, cstr)) } } } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index a8be47e4e..de780e8ce 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -2,24 +2,48 @@ import XCTest @testable import In3 final class In3Tests: XCTestCase { - func testExample() throws { + func testLocal() throws { let in3 = try In3( "{\"chainId\":\"mainnet\"}") let hash = try in3.execLocal("keccak",RPCObject("simon")) switch hash { case let .string(value): XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") default: - XCTAssertTrue(false, "Invalid return type") + XCTFail("Invalid return type") } + } + func testJSON() throws { + let in3 = try In3( "{\"chainId\":\"mainnet\"}") let res = in3.executeJSON("{\"method\":\"keccak\",\"params\":[\"simon\"]}") - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. XCTAssertEqual(res , "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a\"}") } + func testExec() throws { + let expect = XCTestExpectation(description: "Should get a hash-value") + let in3 = try In3( "{\"chainId\":\"mainnet\"}") + try in3.exec("keccak", RPCObject("simon"), cb: { result in + switch result { + case let .error(msg): + XCTFail(msg) + case let .success(hash): + switch hash { + case let .string(value): + XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") + default: + XCTFail("Invalid return type") + } + + } + + }) + wait(for: [expect], timeout: 10) + } + + static var allTests = [ - ("testExample", testExample), + ("testLocal", testLocal), + ("testJSON", testJSON), + ("testExec", testExec), ] } From 92c5fb3f9800a2542c7bb12676b7a3d648fcaddd Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 22:02:51 +0200 Subject: [PATCH 087/221] add linker settings --- swift/Package.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/swift/Package.swift b/swift/Package.swift index a432c84d8..747144443 100644 --- a/swift/Package.swift +++ b/swift/Package.swift @@ -21,7 +21,10 @@ let package = Package( name: "CIn3"), .target( name: "In3", - dependencies: ["CIn3"]), + dependencies: ["CIn3"], + linkerSettings: [ + .unsafeFlags(["-L../build/lib"]) + ]), .testTarget( name: "In3Tests", dependencies: ["In3"]), From c211b3dc17f06215acc011cadd83e30d3a803def Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 22:15:55 +0200 Subject: [PATCH 088/221] fix async tests --- swift/Tests/In3Tests/In3Tests.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index de780e8ce..22dd3ef74 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -30,6 +30,7 @@ final class In3Tests: XCTestCase { switch hash { case let .string(value): XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") + expect.fulfill() default: XCTFail("Invalid return type") } From 3cd86227b03eaa2ff5a34eac29dd3a8512f6f4b8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 4 Apr 2021 22:22:09 +0200 Subject: [PATCH 089/221] optimize --- swift/Tests/In3Tests/In3Tests.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 22dd3ef74..d416de810 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -22,8 +22,8 @@ final class In3Tests: XCTestCase { func testExec() throws { let expect = XCTestExpectation(description: "Should get a hash-value") let in3 = try In3( "{\"chainId\":\"mainnet\"}") - try in3.exec("keccak", RPCObject("simon"), cb: { result in - switch result { + try in3.exec("keccak", RPCObject("simon"), cb: { + switch $0 { case let .error(msg): XCTFail(msg) case let .success(hash): @@ -36,7 +36,6 @@ final class In3Tests: XCTestCase { } } - }) wait(for: [expect], timeout: 10) } From 37d5adcc787a37b9ace67d18e7afc2b3145b7635 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 08:25:23 +0200 Subject: [PATCH 090/221] added in3_new_clone --- c/include/in3/request.h | 11 ++++ c/src/core/client/request.c | 10 ++++ c/src/core/client/request.h | 11 ++++ swift/Sources/In3/In3.swift | 2 +- swift/Sources/In3/Utils/Transport.swift | 72 +++++++++++++++++++++---- swift/Tests/In3Tests/In3Tests.swift | 2 + 6 files changed, 97 insertions(+), 11 deletions(-) diff --git a/c/include/in3/request.h b/c/include/in3/request.h index 880491aaf..6242f5661 100644 --- a/c/include/in3/request.h +++ b/c/include/in3/request.h @@ -133,6 +133,17 @@ NONULL in3_req_t* req_new( in3_t* client, /**< [in] the client-config. */ const char* req_data /**< [in] the rpc-request as json string. */ ); +/** + * creates a new request but clones the request-data. + * + * the request data will be parsed and represented in the context. + * calling this function will only parse the request data, but not send anything yet. + * + */ +NONULL in3_req_t* req_new_clone( + in3_t* client, /**< [in] the client-config. */ + const char* req_data /**< [in] the rpc-request as json string. */ +); /** * sends a previously created request to nodes and verifies it. * diff --git a/c/src/core/client/request.c b/c/src/core/client/request.c index 01199a878..974d650cb 100644 --- a/c/src/core/client/request.c +++ b/c/src/core/client/request.c @@ -55,6 +55,16 @@ static in3_ret_t in3_plugin_init(in3_req_t* ctx) { return IN3_OK; } +in3_req_t* req_new_clone(in3_t* client, const char* req_data) { + char* data = _strdupn(req_data, -1); + in3_req_t* r = req_new(client, data); + if (r) + in3_cache_add_ptr(&r->cache, data); + else + _free(data); + return r; +} + in3_req_t* req_new(in3_t* client, const char* req_data) { assert_in3(client); assert(req_data); diff --git a/c/src/core/client/request.h b/c/src/core/client/request.h index c1899a287..4436b4c06 100644 --- a/c/src/core/client/request.h +++ b/c/src/core/client/request.h @@ -133,6 +133,17 @@ NONULL in3_req_t* req_new( in3_t* client, /**< [in] the client-config. */ const char* req_data /**< [in] the rpc-request as json string. */ ); +/** + * creates a new request but clones the request-data. + * + * the request data will be parsed and represented in the context. + * calling this function will only parse the request data, but not send anything yet. + * + */ +NONULL in3_req_t* req_new_clone( + in3_t* client, /**< [in] the client-config. */ + const char* req_data /**< [in] the rpc-request as json string. */ +); /** * sends a previously created request to nodes and verifies it. * diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 87cd59964..2ca2caeba 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -4,7 +4,7 @@ import Foundation public class In3 { internal var in3: UnsafeMutablePointer? = nil - public var transport: (_ url: String, _ method:String, _ payload:Data, _ headers: [String], _ cb:(_ data:TransportResult)->Void) -> Void + public var transport: (_ url: String, _ method:String, _ payload:Data?, _ headers: [String], _ cb: @escaping (_ data:TransportResult)->Void) -> Void public init(_ config: String) throws { diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index e952ae244..1abffa280 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -1,8 +1,62 @@ import Foundation import CIn3 -internal func httpTransfer(_ url: String, _ method:String, _ payload:Data, _ headers: [String], cb:(_ data:TransportResult)->Void) { - cb(TransportResult.error("Not implemented",-7)) +internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ headers: [String], cb:@escaping (_ data:TransportResult)->Void) { + + guard let url = URL(string:surl) else { + DispatchQueue.main.async { + cb(TransportResult.error("no valid url",-7)) + } + return + } + + let reqStart = Date() + var request = URLRequest(url: url) + request.httpMethod = method + request.httpBody = payload + if method == "POST" { + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + request.addValue("application/json", forHTTPHeaderField: "Accept") + } + for h in headers { + let tokens:[String] = h.split(separator: ":", maxSplits: 2).map { String($0).trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) } + if tokens.count == 2 { + request.addValue(tokens[1], forHTTPHeaderField: tokens[0]) + } + } + URLSession.shared.dataTask(with: request,completionHandler: { data, response, error in + + if let err = error { + DispatchQueue.main.async { + cb(TransportResult.error("Could not send request : \(err)", 500)) + } + return + } + guard let resp = response as? HTTPURLResponse else { + DispatchQueue.main.async { + cb(TransportResult.error("Invalid response", 500)) + } + return + } + guard let d = data else { + DispatchQueue.main.async { + cb(TransportResult.error("No data", 500)) + } + return + } + if resp.statusCode < 400 && resp.statusCode >= 200 { + DispatchQueue.main.async { + cb(TransportResult.success(d, Int(Date().timeIntervalSince(reqStart)*1000))) + } + } else { + DispatchQueue.main.async { + cb(TransportResult.error("Invalid Status :\(resp.statusCode)", resp.statusCode)) + } + } + }).resume() + + + } @@ -13,7 +67,7 @@ internal class In3Request { var freed: Bool init(_ method: String, _ params: [RPCObject],_ _in3:In3, _ _cb: @escaping (_ result:RequestResult)->Void) throws { - let r = req_new(_in3.in3, String(decoding: try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))), as: UTF8.self)) + let r = req_new_clone(_in3.in3, String(decoding: try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))), as: UTF8.self)) if let r = r { req = r } @@ -106,14 +160,12 @@ internal class In3Request { // set the response... switch res { case let .success(data, time): - let ptr = data.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } - if let p = ptr { - in3_ctx_add_response(req,Int32(i),0,p,Int32(data.count), UInt32(time)) + data.withUnsafeBytes { + in3_ctx_add_response(req,Int32(i),0,$0.baseAddress?.assumingMemoryBound(to: Int8.self),Int32(data.count), UInt32(time)) } case let .error(msg,httpStatus): - let ptr = msg.data(using: .utf8)!.withUnsafeBytes { ptr in return ptr.baseAddress?.assumingMemoryBound(to: Int8.self) } - if let p = ptr { - in3_ctx_add_response(req,Int32(i),Int32(-httpStatus),p,Int32(-1), UInt32(0)) + msg.data(using: .utf8)!.withUnsafeBytes { + in3_ctx_add_response(req,Int32(i),Int32(-httpStatus),$0.baseAddress?.assumingMemoryBound(to: Int8.self),Int32(-1), UInt32(0)) } } // now try to verify the response @@ -141,7 +193,7 @@ internal class In3Request { } func sendHttp(http:UnsafeMutablePointer, index:Int, cb:@escaping (_ data:TransportResult)->Void) { - let payload = Data(buffer:UnsafeMutableBufferPointer(start: http.pointee.payload, count: Int(http.pointee.payload_len))) + let payload:Data? = http.pointee.payload_len == 0 ? nil : Data(buffer:UnsafeMutableBufferPointer(start: http.pointee.payload, count: Int(http.pointee.payload_len))) var headers:[String] = [] var p = http.pointee.headers let url = http.pointee.urls + index diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index d416de810..87627dd71 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -1,4 +1,5 @@ import XCTest +import Foundation @testable import In3 final class In3Tests: XCTestCase { @@ -41,6 +42,7 @@ final class In3Tests: XCTestCase { } + static var allTests = [ ("testLocal", testLocal), ("testJSON", testJSON), From c64029d282f66ad3263540ae10795905ad9a903a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 09:53:52 +0200 Subject: [PATCH 091/221] add test-reports --- scripts/create_swift_junit.js | 40 +++++++++++++++++++++++++++++++++++ swift/ci.yml | 8 +++++-- 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100755 scripts/create_swift_junit.js diff --git a/scripts/create_swift_junit.js b/scripts/create_swift_junit.js new file mode 100755 index 000000000..059ae2758 --- /dev/null +++ b/scripts/create_swift_junit.js @@ -0,0 +1,40 @@ +#!/usr/bin/env node + +const readline = require('readline'); +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false +}); +let content = '' +let suite = '' +console.log("\n\n") +rl.on('line', line => { + if (line.startsWith('Test Suite')) return + + if (line.startsWith('Test Case')) { + if (line.indexOf('started') > 0) { + const m = (/\[([a-zA-Z0-9\.]+)\s+(\w+)/gm).exec(line) + content = '' + if (m[1] != suite) { + if (suite) console.log(' ') + console.log(' ') + } + console.log(' ') + } + else { + if (line.indexOf(' failed ') > 0) + console.log(' ') + console.log(' ') + } + } + else + content += line + '\n' +}) +rl.on('close', () => { + console.log(" \n") +}) \ No newline at end of file diff --git a/swift/ci.yml b/swift/ci.yml index 67626b2fb..40df0ce26 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -25,8 +25,12 @@ swift: - cd build - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DTRANSPORTS=false -DUSE_CURL=false -DCMD=false .. && make && rm -f lib/libin3.dylib - cd ../swift - - swift build -Xlinker -L../build/lib - - swift test -Xlinker -L../build/lib + - swift build + - swift test 2> output + - cat output + - ../scripts/create_swift_junit.js < output >swift.xml artifacts: + reports: + junit: swift/swift.xml paths: - swift/.build From ea4500323da74d94aa4cf54423b5c53a7c85b535 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 14:42:32 +0200 Subject: [PATCH 092/221] generate documentation --- c/src/core/client/rpc.yml | 8 +- c/src/nodeselect/full/rpc.yml | 1 + scripts/_in3.sh | 4 +- scripts/build_rpc_docu.js | 50 ++++- swift/Sources/In3/Config.swift | 320 ++++++++++++++++++++++++++++ swift/Sources/In3/In3.swift | 11 +- swift/Tests/In3Tests/In3Tests.swift | 12 +- swift/docs/1_intro.md | 13 ++ 8 files changed, 401 insertions(+), 18 deletions(-) create mode 100644 swift/Sources/In3/Config.swift create mode 100644 swift/docs/1_intro.md diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index d408c78de..080c3c148 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -9,7 +9,7 @@ in3: config: chainId: - type: uint | string + type: string | uint descr: the chainId or the name of a known chain. It defines the nodelist to connect to. example: goerli optional: true @@ -89,9 +89,9 @@ in3: type: string optional: true enum: - - none - - standard - - full + none: no proof will be generated or verfiied. This also works with standard rpc-endpoints. + standard: Stanbdard Proof means all important properties are verfiied + full: In addition to standard, also some rarly needed properties are verfied, like uncles. But this causes a bigger payload. example: none default: standard cmd: p diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 644d4b932..492ecd7d1 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -100,6 +100,7 @@ in3: verifiedHashes: descr: if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. optional: true + array : true type: block: descr: block number diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 58f4ac903..d0e2cf7a9 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -107,8 +107,8 @@ args=( '--experimental[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' '-x[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' '--timeout=[specifies the number of milliseconds before the request times out]:timeout:()' -'--proof=[if true the nodes should send a proof of the response]:proof:(0 1 2)' -'-p[if true the nodes should send a proof of the response]:proof:(0 1 2)' +'--proof=[if true the nodes should send a proof of the response]:proof:(none standard full)' +'-p[if true the nodes should send a proof of the response]:proof:(none standard full)' '--replaceLatestBlock=[if specified, the blocknumber *latest* will be replaced by blockNumber- specified value]:replaceLatestBlock:()' '-l[if specified, the blocknumber *latest* will be replaced by blockNumber- specified value]:replaceLatestBlock:()' '--autoUpdateList[if true the nodelist will be automaticly updated if the lastBlock is newer]' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 874556463..2bc56231f 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -8,8 +8,25 @@ const config_doc = [] const main_help = [] const main_aliases = [] const bool_props = [] +const config_bindings = { + swift: { + Config: [ + '/// The main Incubed Configuration', + 'public struct Config : Codable {' + ] + } +} let docs = {}, config = {}, types = {} +const camelCaseUp = s => { + if (!s) return '' + if (s[s.length - 1] == '.') s = s.substr(0, s.length - 1) + s = s.substr(s.lastIndexOf('.') + 1) + return s.substr(0, 1).toUpperCase() + s.substr(1) +} + +const camelCaseLow = s => s ? s.substr(0, 1).toLowerCase() + s.substr(1) : '' + const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' const getType = val => typeof val === 'object' ? val : (types['' + val] || val) @@ -53,10 +70,37 @@ function print_object(def, pad, useNum, doc) { } } + function handle_config(conf, pre, title, descr) { if (title) config_doc.push('\n## ' + title + '\n') for (const key of Object.keys(conf)) { const c = conf[key] + // handle bindings + + const swift = config_bindings.swift['Config' + camelCaseUp(pre || '')] + if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { + //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) + let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) + if (typeof c.type === 'object') { + swiftType = 'Config' + camelCaseUp(key) + config_bindings.swift[swiftType] = [ + '/// ' + c.descr.replace(/\n/gm, '\n/// '), + 'public struct ' + swiftType + ' : Codable {' + ] + } + else if (swiftType == 'Uint') swiftType = 'UInt64' + else if (swiftType.startsWith('Byte') || swiftType.startsWith('Address')) swiftType = 'String' + if (swiftType.endsWith('[]')) swiftType = '[' + swiftType.substr(0, swiftType.length - 2) + ']' + if (c.array) swiftType = '[' + swiftType + ']' + swift.push('\n /// ' + ( + c.descr + + (c.default ? ('\n(default: `' + JSON.stringify(c.default) + '`)') : '') + + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') + + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex)).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') + ).replace(/\n/gm, '\n /// ')) + swift.push(' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) + } + // handle doc if (!pre) { let s = '\n' + (title ? '#' : '') + '## ' + key + '\n\n' + c.descr if (c.optional) s += ' *This config is optional.*' @@ -200,6 +244,11 @@ for (const s of Object.keys(docs).sort()) { } handle_config(config, '') +fs.writeFileSync('../swift/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( + Object.keys(config_bindings.swift).map(type => config_bindings.swift[type].join('\n') + '\n}\n\n').join('') +), { encoding: 'utf8' }) + + handle_config(main_conf.config, '', 'cmdline options\n\nThose special options are used in the comandline client to pass additional options.\n') main_help.push('') main_help.push('In addition to the documented rpc-methods, those methods are also supported:') @@ -214,4 +263,3 @@ fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'ut fs.writeFileSync(doc_dir + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) fs.writeFileSync('../c/src/cmd/in3/args.h', '// This is a generated file, please don\'t edit it manually!\n\n#include \n\nconst char* bool_props[]={ ' + bool_props.map(_ => '"' + _ + '", ').join('') + ' NULL};\n\nconst char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) - diff --git a/swift/Sources/In3/Config.swift b/swift/Sources/In3/Config.swift new file mode 100644 index 000000000..e4f081a4c --- /dev/null +++ b/swift/Sources/In3/Config.swift @@ -0,0 +1,320 @@ +// This is a generated file, please don't edit it manually! + +import Foundation + +/// The main Incubed Configuration +public struct Config : Codable { + + /// the chainId or the name of a known chain. It defines the nodelist to connect to. + /// (default: `"mainnet"`) + /// + /// Possible Values are: + /// + /// - `mainnet` : Mainnet Chain + /// - `goerli` : Goerli Testnet + /// - `ewc` : Energy WebFoundation + /// - `btc` : Bitcoin + /// - `ipfs` : ipfs + /// - `local` : local-chain + /// + /// + /// Example: `goerli + /// ` + public var chainId : String? + + /// the number in percent needed in order reach finality (% of signature of the validators). + /// + /// Example: `50 + /// ` + public var finality : UInt64? + + /// if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. + /// + /// Example: `true + /// ` + public var includeCode : Bool? + + /// max number of attempts in case a response is rejected. + /// (default: `7`) + /// + /// Example: `1 + /// ` + public var maxAttempts : UInt64? + + /// if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. + /// + /// Example: `true + /// ` + public var keepIn3 : Bool? + + /// if true, requests sent will be used for stats. + /// (default: `true`) + public var stats : Bool? + + /// if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. + /// + /// Example: `true + /// ` + public var useBinary : Bool? + + /// iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. + /// + /// Example: `true + /// ` + public var experimental : Bool? + + /// specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. + /// (default: `20000`) + /// + /// Example: `100000 + /// ` + public var timeout : UInt64? + + /// if true the nodes should send a proof of the response. If set to none, verification is turned off completly. + /// (default: `"standard"`) + /// + /// Possible Values are: + /// + /// - `none` : no proof will be generated or verfiied. This also works with standard rpc-endpoints. + /// - `standard` : Stanbdard Proof means all important properties are verfiied + /// - `full` : In addition to standard, also some rarly needed properties are verfied, like uncles. But this causes a bigger payload. + /// + /// + /// Example: `none + /// ` + public var proof : String? + + /// if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. + /// + /// Example: `6 + /// ` + public var replaceLatestBlock : UInt64? + + /// if true the nodelist will be automaticly updated if the lastBlock is newer. + /// (default: `true`) + public var autoUpdateList : Bool? + + /// number of signatures requested in order to verify the blockhash. + /// (default: `1`) + /// + /// Example: `2 + /// ` + public var signatureCount : UInt64? + + /// if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. + /// (default: `true`) + /// + /// Example: `true + /// ` + public var bootWeights : Bool? + + /// if true the client will try to use http instead of https. + /// + /// Example: `true + /// ` + public var useHttp : Bool? + + /// min stake of the server. Only nodes owning at least this amount will be chosen. + /// + /// Example: `10000000 + /// ` + public var minDeposit : UInt64? + + /// used to identify the capabilities of the node. + /// + /// Example: `65535 + /// ` + public var nodeProps : UInt64? + + /// the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. + /// (default: `2`) + /// + /// Example: `3 + /// ` + public var requestCount : UInt64? + + /// url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. + /// + /// Example: `http://loalhost:8545 + /// ` + public var rpc : String? + + /// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. + /// + /// Example: `contract: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f" + /// nodeList: + /// - address: "0x45d45e6ff99e6c34a235d263965910298985fcfe" + /// url: https://in3-v2.slock.it/mainnet/nd-1 + /// props: "0xFFFF" + /// ` + public var nodes : ConfigNodes? + + /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + /// + /// Example: + /// ``` + /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" + /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" + /// signer_type: contract + /// + /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" + /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" + /// signer_type: create2 + /// create2: + /// creator: "0x6487c3ae644703c1f07527c18fe5569592654bcb" + /// saltarg: "0xb90306e2391fefe48aa89a8e91acbca502a94b2d734acc3335bb2ff5c266eb12" + /// codehash: "0xd6af3ee91c96e29ddab0d4cb9b5dd3025caf84baad13bef7f2b87038d38251e5" + /// + /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" + /// signer_type: pk + /// musig_pub_keys: 0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d8160x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816 + /// sync_key: "0xe8f2ee64be83c0ab9466b0490e4888dbf5a070fd1d82b567e33ebc90457a5734" + /// musig_urls: + /// - null + /// - https://approver.service.com + /// + /// ``` + public var zksync : ConfigZksync? + + /// the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + /// + /// Example: `"0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" + /// ` + public var key : String? + + /// registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + /// + /// Example: + /// ``` + /// "0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" + /// + /// ``` + public var pk : String? + + /// configure the Bitcoin verification + /// + /// Example: `maxDAP: 30 + /// maxDiff: 5 + /// ` + public var btc : ConfigBtc? +} + +/// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. +public struct ConfigNodes : Codable { + + /// address of the registry contract. (This is the data-contract!) + public var contract : String + + /// address of the whiteList contract. This cannot be combined with whiteList! + public var whiteListContract : String? + + /// manual whitelist. + public var whiteList : String? + + /// identifier of the registry. + public var registryId : String + + /// if set, the nodeList will be updated before next request. + public var needsUpdate : Bool? + + /// average block time (seconds) for this chain. + public var avgBlockTime : UInt64? + + /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. + public var verifiedHashes : [ConfigVerifiedHashes]? + + /// manual nodeList. As Value a array of Node-Definitions is expected. + public var nodeList : [ConfigNodeList]? +} + +/// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. +public struct ConfigVerifiedHashes : Codable { + + /// block number + public var block : UInt64 + + /// verified hash corresponding to block number. + public var hash : String +} + +/// manual nodeList. As Value a array of Node-Definitions is expected. +public struct ConfigNodeList : Codable { + + /// URL of the node. + public var url : String + + /// address of the node + public var address : String + + /// used to identify the capabilities of the node (defaults to 0xFFFF). + public var props : UInt64 +} + +/// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). +public struct ConfigZksync : Codable { + + /// url of the zksync-server (if not defined it will be choosen depending on the chain) + /// (default: `"https://api.zksync.io/jsrpc"`) + public var provider_url : String? + + /// the account to be used. if not specified, the first signer will be used. + public var account : String? + + /// the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. + public var sync_key : String? + + /// address of the main contract- If not specified it will be taken from the server. + public var main_contract : String? + + /// type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. + /// (default: `"pk"`) + /// + /// Possible Values are: + /// + /// - `pk` : Private matching the account is used ( for EOA) + /// - `contract` : Contract Signature based EIP 1271 + /// - `create2` : create2 optionas are used + /// + public var signer_type : String? + + /// concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. + public var musig_pub_keys : String? + + /// a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. + public var musig_urls : [String]? + + /// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + public var create2 : ConfigCreate2? +} + +/// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. +public struct ConfigCreate2 : Codable { + + /// The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory ) + public var creator : String + + /// a salt-argument, which will be added to the pubkeyhash and create the create2-salt. + public var saltarg : String + + /// the hash of the actual deploy-tx including the constructor-arguments. + public var codehash : String +} + +/// configure the Bitcoin verification +public struct ConfigBtc : Codable { + + /// max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. + /// (default: `20`) + /// + /// Example: `10 + /// ` + public var maxDAP : UInt64? + + /// max increase (in percent) of the difference between targets when accepting new targets. + /// (default: `10`) + /// + /// Example: `5 + /// ` + public var maxDiff : UInt64? +} + diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 2ca2caeba..f50479849 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -1,13 +1,13 @@ import CIn3 import Foundation - +/// The I ncubed client public class In3 { internal var in3: UnsafeMutablePointer? = nil + /// the transport function public var transport: (_ url: String, _ method:String, _ payload:Data?, _ headers: [String], _ cb: @escaping (_ data:TransportResult)->Void) -> Void - - public init(_ config: String) throws { + public init(_ config: Config) throws { transport = httpTransfer in3 = in3_for_chain_auto_init(1) try configure(config) @@ -17,8 +17,9 @@ public class In3 { in3_free(in3) } - public func configure(_ config: String) throws { - let error = in3_configure(in3, config) + public func configure(_ config: Config) throws { + let jsonConfig = try JSONEncoder().encode(config) + let error = in3_configure(in3, String(decoding: jsonConfig, as: UTF8.self)) if let msg = error { throw IncubedError.config(message: String(cString: msg)) } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 87627dd71..5213d3f31 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -4,7 +4,7 @@ import Foundation final class In3Tests: XCTestCase { func testLocal() throws { - let in3 = try In3( "{\"chainId\":\"mainnet\"}") + let in3 = try In3(Config(chainId: "mainnet")) let hash = try in3.execLocal("keccak",RPCObject("simon")) switch hash { case let .string(value): @@ -15,14 +15,14 @@ final class In3Tests: XCTestCase { } func testJSON() throws { - let in3 = try In3( "{\"chainId\":\"mainnet\"}") + let in3 = try In3(Config(chainId: "mainnet")) let res = in3.executeJSON("{\"method\":\"keccak\",\"params\":[\"simon\"]}") XCTAssertEqual(res , "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a\"}") } func testExec() throws { let expect = XCTestExpectation(description: "Should get a hash-value") - let in3 = try In3( "{\"chainId\":\"mainnet\"}") + let in3 = try In3(Config(chainId: "mainnet")) try in3.exec("keccak", RPCObject("simon"), cb: { switch $0 { case let .error(msg): @@ -44,8 +44,8 @@ final class In3Tests: XCTestCase { static var allTests = [ - ("testLocal", testLocal), - ("testJSON", testJSON), - ("testExec", testExec), + ("execlocal", testLocal), + ("execJSON", testJSON), + ("exec", testExec), ] } diff --git a/swift/docs/1_intro.md b/swift/docs/1_intro.md new file mode 100644 index 000000000..eae6f2ce7 --- /dev/null +++ b/swift/docs/1_intro.md @@ -0,0 +1,13 @@ +# API Reference Swift + +The swift binding contains binaries are only available for macos and ios. + +## Install + + +TODO + +## Classes + + + From 48908d14c8341f8a435452557e2e5cf7224172ed Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 17:27:12 +0200 Subject: [PATCH 093/221] fixed escaped json-parser --- c/src/cmd/in3/args.h | 2 +- c/src/core/util/data.c | 19 +++- scripts/build_rpc_docu.js | 7 +- swift/Sources/In3/API/Eth.swift | 13 +++ swift/Sources/In3/Config.swift | 70 +++++---------- swift/Sources/In3/Utils/Convert.swift | 43 +++++++++ swift/Sources/In3/Utils/Promise.swift | 112 ++++++++++++++++++++++++ swift/Sources/In3/Utils/Transport.swift | 6 +- 8 files changed, 218 insertions(+), 54 deletions(-) create mode 100644 swift/Sources/In3/API/Eth.swift create mode 100644 swift/Sources/In3/Utils/Convert.swift create mode 100644 swift/Sources/In3/Utils/Promise.swift diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 534eb5ab3..53c560f3c 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,7 +2,7 @@ #include -const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ diff --git a/c/src/core/util/data.c b/c/src/core/util/data.c index 7ad8bfc56..49ed3dbec 100644 --- a/c/src/core/util/data.c +++ b/c/src/core/util/data.c @@ -418,7 +418,8 @@ NONULL int parse_string(json_ctx_t* jp, d_token_t* item) { char* start = jp->c; size_t l, i; int n; - bool ishex = false; + bool ishex = false; + int escape = 0; while (true) { switch (*(jp->c++)) { @@ -470,13 +471,25 @@ NONULL int parse_string(json_ctx_t* jp, d_token_t* item) { // here we do change or fix the input string because this would be an invalid string otherwise. *(jp->c - 1) = (*(start - 1) = '"'); } + l -= escape; item->len = l | T_STRING << 28; item->data = _malloc(l + 1); - memcpy(item->data, start, l); + if (escape) { + char* x = start; + for (size_t n = 0; n < l; n++, x++) { + if (*x == '\\') x++; + item->data[n] = *x; + } + } + else + memcpy(item->data, start, l); item->data[l] = 0; } return 0; - case '\\': jp->c++; break; + case '\\': + jp->c++; + escape++; + break; } } } diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 2bc56231f..3d1cf4130 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -16,6 +16,10 @@ const config_bindings = { ] } } +const api_bindings = { + swift: { + } +} let docs = {}, config = {}, types = {} const camelCaseUp = s => { @@ -77,6 +81,7 @@ function handle_config(conf, pre, title, descr) { const c = conf[key] // handle bindings + // generate swift const swift = config_bindings.swift['Config' + camelCaseUp(pre || '')] if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) @@ -96,7 +101,7 @@ function handle_config(conf, pre, title, descr) { c.descr + (c.default ? ('\n(default: `' + JSON.stringify(c.default) + '`)') : '') + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') - + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex)).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') + + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex).trim()).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') ).replace(/\n/gm, '\n /// ')) swift.push(' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) } diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift new file mode 100644 index 000000000..0271e05eb --- /dev/null +++ b/swift/Sources/In3/API/Eth.swift @@ -0,0 +1,13 @@ +import Foundation + +public class Eth { + internal var in3: In3; + + init(_ in3:In3) { + self.in3 = in3 + } + + public func blockNumber() -> Future { + return execUInt64(in3,"eth_blockNumber") + } +} diff --git a/swift/Sources/In3/Config.swift b/swift/Sources/In3/Config.swift index e4f081a4c..dce292f8a 100644 --- a/swift/Sources/In3/Config.swift +++ b/swift/Sources/In3/Config.swift @@ -18,33 +18,28 @@ public struct Config : Codable { /// - `local` : local-chain /// /// - /// Example: `goerli - /// ` + /// Example: `goerli` public var chainId : String? /// the number in percent needed in order reach finality (% of signature of the validators). /// - /// Example: `50 - /// ` + /// Example: `50` public var finality : UInt64? /// if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. /// - /// Example: `true - /// ` + /// Example: `true` public var includeCode : Bool? /// max number of attempts in case a response is rejected. /// (default: `7`) /// - /// Example: `1 - /// ` + /// Example: `1` public var maxAttempts : UInt64? /// if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. /// - /// Example: `true - /// ` + /// Example: `true` public var keepIn3 : Bool? /// if true, requests sent will be used for stats. @@ -53,21 +48,18 @@ public struct Config : Codable { /// if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. /// - /// Example: `true - /// ` + /// Example: `true` public var useBinary : Bool? /// iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. /// - /// Example: `true - /// ` + /// Example: `true` public var experimental : Bool? /// specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. /// (default: `20000`) /// - /// Example: `100000 - /// ` + /// Example: `100000` public var timeout : UInt64? /// if true the nodes should send a proof of the response. If set to none, verification is turned off completly. @@ -80,14 +72,12 @@ public struct Config : Codable { /// - `full` : In addition to standard, also some rarly needed properties are verfied, like uncles. But this causes a bigger payload. /// /// - /// Example: `none - /// ` + /// Example: `none` public var proof : String? /// if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. /// - /// Example: `6 - /// ` + /// Example: `6` public var replaceLatestBlock : UInt64? /// if true the nodelist will be automaticly updated if the lastBlock is newer. @@ -97,46 +87,39 @@ public struct Config : Codable { /// number of signatures requested in order to verify the blockhash. /// (default: `1`) /// - /// Example: `2 - /// ` + /// Example: `2` public var signatureCount : UInt64? /// if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. /// (default: `true`) /// - /// Example: `true - /// ` + /// Example: `true` public var bootWeights : Bool? /// if true the client will try to use http instead of https. /// - /// Example: `true - /// ` + /// Example: `true` public var useHttp : Bool? /// min stake of the server. Only nodes owning at least this amount will be chosen. /// - /// Example: `10000000 - /// ` + /// Example: `10000000` public var minDeposit : UInt64? /// used to identify the capabilities of the node. /// - /// Example: `65535 - /// ` + /// Example: `65535` public var nodeProps : UInt64? /// the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. /// (default: `2`) /// - /// Example: `3 - /// ` + /// Example: `3` public var requestCount : UInt64? /// url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. /// - /// Example: `http://loalhost:8545 - /// ` + /// Example: `http://loalhost:8545` public var rpc : String? /// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. @@ -145,8 +128,7 @@ public struct Config : Codable { /// nodeList: /// - address: "0x45d45e6ff99e6c34a235d263965910298985fcfe" /// url: https://in3-v2.slock.it/mainnet/nd-1 - /// props: "0xFFFF" - /// ` + /// props: "0xFFFF"` public var nodes : ConfigNodes? /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). @@ -156,7 +138,6 @@ public struct Config : Codable { /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" /// signer_type: contract - /// /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" /// signer_type: create2 @@ -164,7 +145,6 @@ public struct Config : Codable { /// creator: "0x6487c3ae644703c1f07527c18fe5569592654bcb" /// saltarg: "0xb90306e2391fefe48aa89a8e91acbca502a94b2d734acc3335bb2ff5c266eb12" /// codehash: "0xd6af3ee91c96e29ddab0d4cb9b5dd3025caf84baad13bef7f2b87038d38251e5" - /// /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" /// signer_type: pk /// musig_pub_keys: 0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d8160x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816 @@ -172,14 +152,12 @@ public struct Config : Codable { /// musig_urls: /// - null /// - https://approver.service.com - /// /// ``` public var zksync : ConfigZksync? /// the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) /// - /// Example: `"0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" - /// ` + /// Example: `"0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe"` public var key : String? /// registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) @@ -187,15 +165,13 @@ public struct Config : Codable { /// Example: /// ``` /// "0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" - /// /// ``` public var pk : String? /// configure the Bitcoin verification /// /// Example: `maxDAP: 30 - /// maxDiff: 5 - /// ` + /// maxDiff: 5` public var btc : ConfigBtc? } @@ -306,15 +282,13 @@ public struct ConfigBtc : Codable { /// max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. /// (default: `20`) /// - /// Example: `10 - /// ` + /// Example: `10` public var maxDAP : UInt64? /// max increase (in percent) of the difference between targets when accepting new targets. /// (default: `10`) /// - /// Example: `5 - /// ` + /// Example: `5` public var maxDiff : UInt64? } diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift new file mode 100644 index 000000000..10539761b --- /dev/null +++ b/swift/Sources/In3/Utils/Convert.swift @@ -0,0 +1,43 @@ + +import Foundation + + + +internal func toUInt64Promise(_ data:RPCObject, _ promise:Promise) { + switch data { + case let .integer(val): + promise.resolve(with: UInt64(val)) + case let .string(val): + if let intVal = UInt64(val) { + promise.resolve(with: intVal) + } else if val.hasPrefix("0x"), let intVal = UInt64(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { + promise.resolve(with: intVal) + } else { + promise.reject(with: IncubedError.rpc(message: "Invalid integer value " + val)) + } + default: + promise.reject(with: IncubedError.rpc(message: "Invalid returntype")) + } +} + + +internal func execUInt64(_ in3:In3, _ method: String, _ params: RPCObject...) -> Future { + let promise = Promise() + do { + try In3Request(method,params,in3,{ + switch $0 { + case let .error(msg): + promise.reject(with: IncubedError.rpc(message: msg)) + case let .success(data): + toUInt64Promise(data,promise) + } + }).exec() + } catch { + promise.reject(with: error) + } + return promise +} + + + + diff --git a/swift/Sources/In3/Utils/Promise.swift b/swift/Sources/In3/Utils/Promise.swift new file mode 100644 index 000000000..284393b3b --- /dev/null +++ b/swift/Sources/In3/Utils/Promise.swift @@ -0,0 +1,112 @@ +/** + * Swift by Sundell sample code + * Copyright (c) John Sundell 2020 + * See LICENSE file for license + * + * Read the article at https://swiftbysundell.com/posts/under-the-hood-of-futures-and-promises-in-swift + */ + +import Foundation + + +public class Future { + public typealias Result = Swift.Result + + fileprivate var result: Result? { + // Observe whenever a result is assigned, and report it: + didSet { result.map(report) } + } + private var callbacks = [(Result) -> Void]() + + public func observe(using callback: @escaping (Result) -> Void) { + // If a result has already been set, call the callback directly: + if let result = result { + return callback(result) + } + + callbacks.append(callback) + } + + private func report(result: Result) { + callbacks.forEach { $0(result) } + callbacks = [] + } +} + +public class Promise: Future { + init(value: Value? = nil) { + super.init() + + // If the value was already known at the time the promise + // was constructed, we can report it directly: + result = value.map(Result.success) + } + + public func resolve(with value: Value) { + result = .success(value) + } + + public func reject(with error: Error) { + result = .failure(error) + } +} + +extension Future { + func chained( + using closure: @escaping (Value) throws -> Future + ) -> Future { + // We'll start by constructing a "wrapper" promise that will be + // returned from this method: + let promise = Promise() + + // Observe the current future: + observe { result in + switch result { + case .success(let value): + do { + // Attempt to construct a new future using the value + // returned from the first one: + let future = try closure(value) + + // Observe the "nested" future, and once it + // completes, resolve/reject the "wrapper" future: + future.observe { result in + switch result { + case .success(let value): + promise.resolve(with: value) + case .failure(let error): + promise.reject(with: error) + } + } + } catch { + promise.reject(with: error) + } + case .failure(let error): + promise.reject(with: error) + } + } + + return promise + } +} + +extension Future { + func transformed( + with closure: @escaping (Value) throws -> T + ) -> Future { + chained { value in + try Promise(value: closure(value)) + } + } +} + +extension Future where Value == Data { + func decoded( + as type: T.Type = T.self, + using decoder: JSONDecoder = .init() + ) -> Future { + transformed { data in + try decoder.decode(T.self, from: data) + } + } +} diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index 1abffa280..eba2491ce 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -5,11 +5,15 @@ internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ h guard let url = URL(string:surl) else { DispatchQueue.main.async { - cb(TransportResult.error("no valid url",-7)) + cb(TransportResult.error("no valid url :"+surl,-7)) } return } +// if let pl = payload { +// print("Request to " , url," payload :"+String(decoding: pl, as: UTF8.self)) +// } + let reqStart = Date() var request = URLRequest(url: url) request.httpMethod = method From f61446996a8892310d5390056808740abff7b6e8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 20:38:41 +0200 Subject: [PATCH 094/221] create eth api --- swift/Sources/In3/API/Eth.swift | 20 ++- swift/Sources/In3/Utils/Convert.swift | 155 +++++++++++++++++++++--- swift/Sources/In3/Utils/Error.swift | 1 + swift/Sources/In3/Utils/Transport.swift | 8 +- swift/Tests/In3Tests/In3Tests.swift | 19 +++ 5 files changed, 183 insertions(+), 20 deletions(-) diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift index 0271e05eb..7c74c2454 100644 --- a/swift/Sources/In3/API/Eth.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -8,6 +8,24 @@ public class Eth { } public func blockNumber() -> Future { - return execUInt64(in3,"eth_blockNumber") + return execAndConvert(in3: in3, method:"eth_blockNumber", convertWith: toUInt64) + } + + public func getTransactionReceipt(hash:String) -> Future { + return execAndConvertOptional(in3: in3, method:"eth_getTransactionReceipt", params:RPCObject(hash),convertWith: { try EthTransactionReceipt($0,$1) } ) + } + + +} + +public struct EthTransactionReceipt { + public var hash: String + + public init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc) else { + return nil + } + + hash = try toString(obj["transactionHash"], false)! } } diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift index 10539761b..7fb27fd6b 100644 --- a/swift/Sources/In3/Utils/Convert.swift +++ b/swift/Sources/In3/Utils/Convert.swift @@ -3,33 +3,135 @@ import Foundation -internal func toUInt64Promise(_ data:RPCObject, _ promise:Promise) { - switch data { - case let .integer(val): - promise.resolve(with: UInt64(val)) - case let .string(val): - if let intVal = UInt64(val) { - promise.resolve(with: intVal) - } else if val.hasPrefix("0x"), let intVal = UInt64(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { - promise.resolve(with: intVal) - } else { - promise.reject(with: IncubedError.rpc(message: "Invalid integer value " + val)) +internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt64?{ + if let data = data { + switch data { + case let .integer(val): + return UInt64(val) + case let .string(val): + if let intVal = UInt64(val) { + return intVal + } else if val.hasPrefix("0x"), let intVal = UInt64(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { + return intVal + } else { + throw IncubedError.config(message: "Can not convert '\(val)' to int") + } + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for Int") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + +internal func toBool(_ data:RPCObject?, _ optional:Bool = true) throws -> Bool?{ + if let data = data { + switch data { + case let .integer(val): + return val != 0; + case let .string(val): + if val == "true" || val=="0x1" { + return true + } else if val == "false" || val == "0x0" { + return false + } else { + throw IncubedError.config(message: "Invalid string to convert '\(val)' to Bool") + } + case let .bool(val): + return val + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for bool") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + + +internal func toString(_ data:RPCObject?, _ optional:Bool = true) throws -> String?{ + if let data = data { + switch data { + case let .integer(val): + return String(val) + case let .string(val): + return val + case let .bool(val): + return val ? "true":"false" + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for String") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + + +internal func toObject(_ data:RPCObject?,_ optional:Bool = true) throws -> [String: RPCObject]?{ + if let data = data { + switch data { + case let .dictionary(val): + return val + case .none: + return nil + default: + throw IncubedError.config(message: "Invalid type for Object") } - default: - promise.reject(with: IncubedError.rpc(message: "Invalid returntype")) } + return nil } -internal func execUInt64(_ in3:In3, _ method: String, _ params: RPCObject...) -> Future { - let promise = Promise() + +internal func toArray(_ data:RPCObject?, _ optional:Bool = true) throws -> [RPCObject]?{ + if let data = data { + switch data { + case let .list(val): + return val + case .none: + return nil + default: + throw IncubedError.config(message: "Invalid type for Array") + } + } + return nil +} + + +internal func execAndConvert(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { + let promise = Promise() do { try In3Request(method,params,in3,{ switch $0 { case let .error(msg): promise.reject(with: IncubedError.rpc(message: msg)) case let .success(data): - toUInt64Promise(data,promise) + do { + if let v = try convertWith(data,false) { + promise.resolve(with: v) + } else { + promise.reject(with: IncubedError.rpc(message: "Null Value is not allowed here")) + } + } catch { + promise.reject(with: error) + } } }).exec() } catch { @@ -38,6 +140,27 @@ internal func execUInt64(_ in3:In3, _ method: String, _ params: RPCObject...) -> return promise } +internal func execAndConvertOptional(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { + let promise = Promise() + do { + try In3Request(method,params,in3,{ + switch $0 { + case let .error(msg): + promise.reject(with: IncubedError.rpc(message: msg)) + case let .success(data): + do { + let val = try convertWith(data, true) + promise.resolve(with: val) + } catch { + promise.reject(with: error) + } + } + }).exec() + } catch { + promise.reject(with: error) + } + return promise +} diff --git a/swift/Sources/In3/Utils/Error.swift b/swift/Sources/In3/Utils/Error.swift index add61c347..ef39d046d 100644 --- a/swift/Sources/In3/Utils/Error.swift +++ b/swift/Sources/In3/Utils/Error.swift @@ -3,6 +3,7 @@ import Foundation public enum IncubedError: Error { case config(message: String) case rpc(message: String) + case convert(message: String) } public enum TransportResult { diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index eba2491ce..7db0a0faa 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -10,9 +10,9 @@ internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ h return } -// if let pl = payload { -// print("Request to " , url," payload :"+String(decoding: pl, as: UTF8.self)) -// } + if let pl = payload { + print("Request to " , url," payload :"+String(decoding: pl, as: UTF8.self)) + } let reqStart = Date() var request = URLRequest(url: url) @@ -48,6 +48,8 @@ internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ h } return } + print("Response : " , String(decoding: d, as: UTF8.self)) + if resp.statusCode < 400 && resp.statusCode >= 200 { DispatchQueue.main.async { cb(TransportResult.success(d, Int(Date().timeIntervalSince(reqStart)*1000))) diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 5213d3f31..d67513e06 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -41,6 +41,25 @@ final class In3Tests: XCTestCase { wait(for: [expect], timeout: 10) } + func testAPI() throws { + let expect = XCTestExpectation(description: "Should get a hash-value") + let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) + Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { + switch $0 { + case let .failure(err): + print(err.localizedDescription) + case let .success( val ): + if let tx = val { + print("txhash : ",tx.hash) + } else { + print("on tx found ") + } + expect.fulfill() + } + }) + wait(for: [expect], timeout: 100) + + } static var allTests = [ From 23454bec0a522d345d79ae917738afd31d2518b5 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Apr 2021 21:11:47 +0200 Subject: [PATCH 095/221] format --- c/src/cmd/in3/args.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 53c560f3c..534eb5ab3 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,7 +2,7 @@ #include -const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ From a6226674fc255f865c900e6a6f8a952ced1a86a7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Apr 2021 00:20:03 +0200 Subject: [PATCH 096/221] added cache --- CMakeLists.txt | 11 ++- c/CMakeLists.txt | 58 +++++++----- c/include/in3.rs.h | 1 + c/include/in3/plugin.h | 6 +- c/src/core/client/plugin.h | 6 +- c/src/tools/CMakeLists.txt | 4 + c/src/tools/swift/CMakeLists.txt | 44 +++++++++ c/src/tools/swift/swift.c | 31 ++++++ c/src/tools/swift/swift.h | 47 ++++++++++ scripts/build_includeh.sh | 1 + swift/Sources/In3/In3.swift | 10 ++ swift/Sources/In3/Utils/Cache.swift | 120 ++++++++++++++++++++++++ swift/Sources/In3/Utils/Transport.swift | 3 - swift/Tests/In3Tests/In3Tests.swift | 7 +- swift/ci.yml | 2 +- 15 files changed, 313 insertions(+), 38 deletions(-) create mode 100644 c/src/tools/swift/CMakeLists.txt create mode 100644 c/src/tools/swift/swift.c create mode 100644 c/src/tools/swift/swift.h create mode 100644 swift/Sources/In3/Utils/Cache.swift diff --git a/CMakeLists.txt b/CMakeLists.txt index 572604744..0a6145a77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,16 +87,25 @@ OPTION(NODESELECT_DEF "Enable default nodeselect implementation" ON) OPTION(NODESELECT_DEF_WL "Enable default nodeselect whitelist implementation" ON) OPTION(PLGN_CLIENT_DATA "Enable client-data plugin" OFF) OPTION(THREADSAFE "uses mutex to protect shared nodelist access" ON) +OPTION(SWIFT "swift API for swift bindings" OFF) IF (DEFINED ANDROID_ABI) set(TRANSPORTS,false) set(IN3_LIB,false) - set(USE_CURL,false) + set(USE_CURL,off) set(CMD,false) set(JAVA,true) set(RECORDER,false) ENDIF() +IF (SWIFT) + set(TRANSPORTS,false) + set(IN3_LIB,true) + set(USE_CURL, false) + set(CMD,false) + set(JAVA,false) + set(RECORDER,false) +ENDIF() IF (BTC_PRE_BPI34) ADD_DEFINITIONS(-DBTC_PRE_BPI34) diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 8bd5899dc..367befaa9 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -46,7 +46,7 @@ if (GCC_ANALYZER) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fanalyzer -Werror") endif() -IF (TRANSPORTS) +IF (TRANSPORTS AND NOT SWIFT) ADD_DEFINITIONS(-DTRANSPORTS) if (USE_CURL) ADD_DEFINITIONS(-DUSE_CURL) @@ -61,7 +61,7 @@ IF (TRANSPORTS) set(IN3_TRANSPORT ${IN3_TRANSPORT} transport_http) endif (USE_CURL) add_subdirectory(src/transport) -ENDIF (TRANSPORTS) +ENDIF (TRANSPORTS AND NOT SWIFT) add_subdirectory(src/core) add_subdirectory(src/init) @@ -80,35 +80,45 @@ link_directories(${CMAKE_BINARY_DIR}/lib/) if (IN3_LIB) get_property(IN3_LIBS GLOBAL PROPERTY IN3_OBJECTS) - # create the libraries + # create static libraries add_library(in3_bundle STATIC ${IN3_LIBS} ) - add_library(in3_lib SHARED ${IN3_LIBS} ) set_target_properties(in3_bundle PROPERTIES OUTPUT_NAME "in3") - set_target_properties(in3_lib PROPERTIES OUTPUT_NAME "in3") - target_link_libraries(in3_lib ${IN3_TRANSPORT}) - if( LEDGER_NANO) - target_link_libraries(in3_lib ledger_signer) - endif() - if(SENTRY) - target_link_libraries(in3_lib sentry) - endif() - if (ZKSYNC AND ZKCRYPTO_LIB ) target_link_libraries(in3_bundle zk_crypto_rs ) - target_link_libraries(in3_lib zk_crypto_rs ) endif() - - - # install INSTALL(TARGETS in3_bundle - DESTINATION "lib" + DESTINATION "lib" ) - INSTALL(TARGETS in3_lib - DESTINATION lib - PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE) + + IF (NOT SWIFT) + + # create shared libraries + add_library(in3_lib SHARED ${IN3_LIBS} ) + set_target_properties(in3_lib PROPERTIES OUTPUT_NAME "in3") + target_link_libraries(in3_lib ${IN3_TRANSPORT}) + + if( LEDGER_NANO) + target_link_libraries(in3_lib ledger_signer) + endif() + if(SENTRY) + target_link_libraries(in3_lib sentry) + endif() + + if (ZKSYNC AND ZKCRYPTO_LIB ) + target_link_libraries(in3_lib zk_crypto_rs ) + endif() + + + # install + INSTALL(TARGETS in3_lib + DESTINATION lib + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) + ENDIF(NOT SWIFT) + + INSTALL ( DIRECTORY ${CMAKE_SOURCE_DIR}/c/include/in3 DESTINATION include diff --git a/c/include/in3.rs.h b/c/include/in3.rs.h index f03fa7636..0eb4f5991 100644 --- a/c/include/in3.rs.h +++ b/c/include/in3.rs.h @@ -13,3 +13,4 @@ #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" +#include "../src/tools/swift/swift.h" diff --git a/c/include/in3/plugin.h b/c/include/in3/plugin.h index 5d8601723..17651aa29 100644 --- a/c/include/in3/plugin.h +++ b/c/include/in3/plugin.h @@ -374,9 +374,9 @@ typedef void (*in3_storage_clear)( * context used during get config */ typedef struct in3_cache_ctx { - in3_req_t* req; /**< the request context */ - char* key; /**< the key to fetch */ - bytes_t* content; /**< the content to set */ + in3_req_t* req; /**< the request context */ + const char* key; /**< the key to fetch */ + bytes_t* content; /**< the content to set */ } in3_cache_ctx_t; /** diff --git a/c/src/core/client/plugin.h b/c/src/core/client/plugin.h index 5d8601723..17651aa29 100644 --- a/c/src/core/client/plugin.h +++ b/c/src/core/client/plugin.h @@ -374,9 +374,9 @@ typedef void (*in3_storage_clear)( * context used during get config */ typedef struct in3_cache_ctx { - in3_req_t* req; /**< the request context */ - char* key; /**< the key to fetch */ - bytes_t* content; /**< the content to set */ + in3_req_t* req; /**< the request context */ + const char* key; /**< the key to fetch */ + bytes_t* content; /**< the content to set */ } in3_cache_ctx_t; /** diff --git a/c/src/tools/CMakeLists.txt b/c/src/tools/CMakeLists.txt index 300dd8bdd..16a6f8319 100644 --- a/c/src/tools/CMakeLists.txt +++ b/c/src/tools/CMakeLists.txt @@ -40,6 +40,10 @@ if(RECORDER) add_subdirectory(recorder) endif() +if(SWIFT) + add_subdirectory(swift) +endif() + if(PLGN_CLIENT_DATA) add_subdirectory(clientdata) endif() diff --git a/c/src/tools/swift/CMakeLists.txt b/c/src/tools/swift/CMakeLists.txt new file mode 100644 index 000000000..e04f9a6a5 --- /dev/null +++ b/c/src/tools/swift/CMakeLists.txt @@ -0,0 +1,44 @@ +############################################################################### +# This file is part of the Incubed project. +# Sources: https://github.com/slockit/in3-c +# +# Copyright (C) 2018-2019 slock.it GmbH, Blockchains LLC +# +# +# COMMERCIAL LICENSE USAGE +# +# Licensees holding a valid commercial license may use this file in accordance +# with the commercial license agreement provided with the Software or, alternatively, +# in accordance with the terms contained in a written agreement between you and +# slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further +# information please contact slock.it at in3@slock.it. +# +# Alternatively, this file may be used under the AGPL license as follows: +# +# AGPL LICENSE USAGE +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU Affero General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +# [Permissions of this strong copyleft license are conditioned on making available +# complete source code of licensed works and modifications, which include larger +# works using a licensed work, under the same license. Copyright and license notices +# must be preserved. Contributors provide an express grant of patent rights.] +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +############################################################################### + +add_static_library( + NAME + in3_swift + + SOURCES + swift.c + + DEPENDS + core +) diff --git a/c/src/tools/swift/swift.c b/c/src/tools/swift/swift.c new file mode 100644 index 000000000..9ec093f0d --- /dev/null +++ b/c/src/tools/swift/swift.c @@ -0,0 +1,31 @@ + +#include "swift.h" + +static in3_ret_t handle(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx) { + swift_cb_t* conf = plugin_data; + switch (action) { + case PLGN_ACT_TERM: + _free(plugin_data); + return IN3_OK; + case PLGN_ACT_CACHE_GET: { + in3_cache_ctx_t* _Nonnull ctx = plugin_ctx; + return conf->cache_get(ctx); + } + case PLGN_ACT_CACHE_SET: { + in3_cache_ctx_t* _Nonnull ctx = plugin_ctx; + return conf->cache_set(ctx); + } + case PLGN_ACT_CACHE_CLEAR: + return conf->cache_clear(); + + default: + return IN3_ENOTSUP; + } + return IN3_EIGNORE; +} + +in3_ret_t in3_register_swift(in3_t* c, swift_cb_t* cbs) { + swift_cb_t* ptr = _malloc(sizeof(swift_cb_t)); + memcpy(ptr, cbs, sizeof(swift_cb_t)); + return in3_plugin_register(c, PLGN_ACT_CACHE_GET | PLGN_ACT_CACHE_SET | PLGN_ACT_CACHE_CLEAR | PLGN_ACT_TERM, handle, ptr, true); +} \ No newline at end of file diff --git a/c/src/tools/swift/swift.h b/c/src/tools/swift/swift.h new file mode 100644 index 000000000..47c8f0030 --- /dev/null +++ b/c/src/tools/swift/swift.h @@ -0,0 +1,47 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/slockit/in3-c + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ +#ifndef IN3_SWIFT_H +#define IN3_SWIFT_H + +#include "../../core/client/plugin.h" + +typedef struct in3_swift_cb { + in3_ret_t (*_Nonnull cache_get)(in3_cache_ctx_t* _Nonnull ctx); + in3_ret_t (*_Nonnull cache_set)(in3_cache_ctx_t* _Nonnull ctx); + in3_ret_t (*_Nonnull cache_clear)(); +} swift_cb_t; + +in3_ret_t in3_register_swift(in3_t* _Nonnull c, swift_cb_t* _Nonnull cbs); + +#endif //IN3_SWIFT_H diff --git a/scripts/build_includeh.sh b/scripts/build_includeh.sh index d4b296480..7437782e3 100755 --- a/scripts/build_includeh.sh +++ b/scripts/build_includeh.sh @@ -47,4 +47,5 @@ cat <../c/include/in3.rs.h #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" +#include "../src/tools/swift/swift.h" EOF diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index f50479849..29f8e097a 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -6,11 +6,21 @@ public class In3 { internal var in3: UnsafeMutablePointer? = nil /// the transport function public var transport: (_ url: String, _ method:String, _ payload:Data?, _ headers: [String], _ cb: @escaping (_ data:TransportResult)->Void) -> Void + + var cache: In3Cache? { + get { + return defaultCache + } + set(value) { + defaultCache = value + } + } public init(_ config: Config) throws { transport = httpTransfer in3 = in3_for_chain_auto_init(1) try configure(config) + registerCache(self) } deinit { diff --git a/swift/Sources/In3/Utils/Cache.swift b/swift/Sources/In3/Utils/Cache.swift new file mode 100644 index 000000000..958c0409f --- /dev/null +++ b/swift/Sources/In3/Utils/Cache.swift @@ -0,0 +1,120 @@ +import Foundation +import CIn3 + +public protocol In3Cache { + func getEntry(key:String)->Data? + func setEntry(key:String,value:Data)->Void + func clear()->Void +} + + +public class FileCache : In3Cache { + var dir:URL + + convenience init() throws { + try self.init(URL(fileURLWithPath: ".in3", relativeTo: FileManager.default.homeDirectoryForCurrentUser)) + } + convenience init(_ dir:String) throws { + try self.init(URL(fileURLWithPath: dir, isDirectory: true)) + } + + init(_ dir:URL) throws { + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) + self.dir = dir + } + + public func setEntry(key: String, value: Data) { + do { + try value.write(to: URL(fileURLWithPath: key, relativeTo: dir)) + } catch { + } + } + + public func getEntry(key: String) -> Data? { + do { + return try Data(contentsOf: URL(fileURLWithPath: key, relativeTo: dir)) + } catch { + return nil + } + } + + public func clear() { + do { + try FileManager.default.removeItem(at: dir) + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) + } catch { + } + } +} + +internal var defaultCache:In3Cache? + +internal func registerCache(_ in3:In3) { + if defaultCache == nil { + do { + defaultCache = try FileCache() + } catch { + print("Could not init the cache : \(error)") + } + } + var cbs = swift_cb_t( + cache_get: { ctx -> in3_ret_t in + if let cache = defaultCache { + let key = String(cString: ctx.pointee.key) + let value = cache.getEntry(key: key) + if let data = value { + data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer ) in + ctx.pointee.content = b_new(ptr.baseAddress?.assumingMemoryBound(to: UInt8.self), UInt32(data.count)) + } + return IN3_OK + } else { + return IN3_EIGNORE + } + } + return IN3_OK + }, + cache_set: { ctx -> in3_ret_t in + if let cache = defaultCache { + let key = String(cString: ctx.pointee.key) + cache.setEntry(key: key, value: Data(bytes: ctx.pointee.content.pointee.data, count: Int(ctx.pointee.content.pointee.len))) + return IN3_OK + } + return IN3_EIGNORE + }, + cache_clear: { + if let cache = defaultCache { + cache.clear() + } + return IN3_OK + } + ) + + if let in3ptr = in3.in3 { + in3_register_swift(in3ptr, &cbs) + } + + + /* + let callbacks = callbacks( + cl + + printGreeting: { (modifier) in + printGreeting(modifier: modifier) + } + ) + */ +} + +/* + +private func printGreeting(modifier: UnsafePointer) { + print("Hello \(String(cString: modifier))World!") +} + +var callbacks = SomeCLibCallbacks( + printGreeting: { (modifier) in + printGreeting(modifier: modifier) + } +) +SomeCLibSetup(&callbacks) +*/ diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift index 7db0a0faa..2610890b9 100644 --- a/swift/Sources/In3/Utils/Transport.swift +++ b/swift/Sources/In3/Utils/Transport.swift @@ -60,9 +60,6 @@ internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ h } } }).resume() - - - } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index d67513e06..798a8b691 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -38,12 +38,13 @@ final class In3Tests: XCTestCase { } }) - wait(for: [expect], timeout: 10) + wait(for: [expect], timeout: 1000) } func testAPI() throws { let expect = XCTestExpectation(description: "Should get a hash-value") - let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) +// let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) + let in3 = try In3(Config(chainId: "mainnet")) Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { switch $0 { case let .failure(err): @@ -57,7 +58,7 @@ final class In3Tests: XCTestCase { expect.fulfill() } }) - wait(for: [expect], timeout: 100) + wait(for: [expect], timeout: 10) } diff --git a/swift/ci.yml b/swift/ci.yml index 40df0ce26..33434f4b7 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -23,7 +23,7 @@ swift: script: - mkdir build - cd build - - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DTRANSPORTS=false -DUSE_CURL=false -DCMD=false .. && make && rm -f lib/libin3.dylib + - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DSWIFT .. && make - cd ../swift - swift build - swift test 2> output From 3448aa7e7503deee6b5b2cd3a0909ed41d4c8934 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Apr 2021 00:29:24 +0200 Subject: [PATCH 097/221] fix ci --- swift/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ci.yml b/swift/ci.yml index 33434f4b7..7c2120cd0 100644 --- a/swift/ci.yml +++ b/swift/ci.yml @@ -23,7 +23,7 @@ swift: script: - mkdir build - cd build - - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DSWIFT .. && make + - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DSWIFT=true .. && make - cd ../swift - swift build - swift test 2> output From c503f13ffce02aa13095ec629ff685226b340e08 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Apr 2021 00:40:34 +0200 Subject: [PATCH 098/221] fix const key --- c/src/pay/zksync/zk_incentive.c | 10 ++++++---- scripts/build.sh | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/c/src/pay/zksync/zk_incentive.c b/c/src/pay/zksync/zk_incentive.c index 7a232aab3..563e62f45 100644 --- a/c/src/pay/zksync/zk_incentive.c +++ b/c/src/pay/zksync/zk_incentive.c @@ -105,8 +105,9 @@ static in3_ret_t set_amount(zk_fee_t* dst, in3_req_t* ctx, d_token_t* t) { } static in3_ret_t get_payed_addresses(in3_req_t* ctx, bytes_t* dst) { - in3_cache_ctx_t c = {.content = NULL, .req = ctx, .key = alloca(20)}; - sprintf(c.key, "payed_%d", (uint32_t) ctx->client->chain.chain_id); + char key[20]; + sprintf(key, "payed_%d", (uint32_t) ctx->client->chain.chain_id); + in3_cache_ctx_t c = {.content = NULL, .req = ctx, .key = key}; TRY(in3_plugin_execute_first_or_none(ctx, PLGN_ACT_CACHE_GET, &c)) if (c.content) { *dst = *c.content; @@ -117,8 +118,9 @@ static in3_ret_t get_payed_addresses(in3_req_t* ctx, bytes_t* dst) { static in3_ret_t update_payed_addresses(in3_req_t* ctx, unsigned int nodes, bytes_t payed, bool update_cache) { if (update_cache) { - in3_cache_ctx_t c = {.content = &payed, .req = ctx, .key = alloca(20)}; - sprintf(c.key, "payed_%d", (uint32_t) ctx->client->chain.chain_id); + char key[20]; + sprintf(key, "payed_%d", (uint32_t) ctx->client->chain.chain_id); + in3_cache_ctx_t c = {.content = &payed, .req = ctx, .key = key}; TRY(in3_plugin_execute_first_or_none(ctx, PLGN_ACT_CACHE_SET, &c)) } diff --git a/scripts/build.sh b/scripts/build.sh index 527309661..faa5bb2b0 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -114,7 +114,7 @@ elif [ "$CONTAINER" = "android" ]; then docker run --rm -v $RD:$RD $CONTAINER /bin/bash -c "$CMD" elif [ "$CONTAINER" = "wasm_local" ]; then cd build - source ~/ws/tools/emsdk/emsdk_env.sh > /dev/null +# source ~/ws/tools/emsdk/emsdk_env.sh > /dev/null emcmake cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=true -DWASM=true -DASMJS=false -DWASM_EMMALLOC=true -DIPFS=false -DZKSYNC=true -DWASM_EMBED=false -DCMAKE_BUILD_TYPE=$BUILDTYPE .. make -j8 in3_wasm elif [ "$CONTAINER" = "wasm" ]; then From f5c058d36364dd1373626ed764d9df45822e2238 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Apr 2021 13:40:08 +0200 Subject: [PATCH 099/221] updated documentation and refactored Config --- scripts/build_rpc_docu.js | 50 +++- swift/Sources/In3/API/Eth.swift | 16 +- swift/Sources/In3/Config.swift | 337 ++++++++++++++++++-------- swift/Sources/In3/In3.swift | 4 +- swift/Sources/In3/Utils/Cache.swift | 42 ++-- swift/Sources/In3/Utils/Convert.swift | 12 +- swift/Sources/In3/Utils/Error.swift | 21 +- swift/Sources/In3/Utils/JsonRpc.swift | 34 +++ swift/Tests/In3Tests/In3Tests.swift | 8 +- swift/Tests/In3Tests/Mock.swift | 10 + swift/docs/1_intro.md | 27 ++- 11 files changed, 410 insertions(+), 151 deletions(-) create mode 100644 swift/Tests/In3Tests/Mock.swift diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 3d1cf4130..5a7ea627c 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -10,9 +10,15 @@ const main_aliases = [] const bool_props = [] const config_bindings = { swift: { - Config: [ + In3Config: [ '/// The main Incubed Configuration', - 'public struct Config : Codable {' + 'public struct In3Config : Codable {', + '', + ' /// create a new Incubed Client based on the Configuration', + ' public func createClient() throws -> In3 {', + ' return try In3(self)', + ' }', + '' ] } } @@ -35,6 +41,26 @@ const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val] const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' const getType = val => typeof val === 'object' ? val : (types['' + val] || val) const toCmdParam = val => (typeof val == 'object' || Array.isArray(val) || ('' + val).indexOf(' ') >= 0) ? "'" + JSON.stringify(val) + "'" : ('' + val) +function createSwiftInitForStruct(s, pad) { + let comments = '\n' + pad + ' /// initialize it memberwise' + let code = '' + let init = '' + let lastDescr = '' + for (let l of s) { + l = l.trim() + if (lastDescr && !l) lastDescr = '' + if (!lastDescr && l.startsWith('/// ')) lastDescr = l.substr(4).split('\n')[0].trim() + if (l.startsWith('public var ')) { + l = l.substr('public var '.length) + const pname = l.substr(0, l.indexOf(':')).trim() + comments += '\n' + pad + ' /// - Parameter ' + pname + ' : ' + lastDescr + code += '\n' + pad + ' self.' + pname + ' = ' + pname + init += (init ? ', ' : '') + l + (l.endsWith('?') ? ' = nil' : '') + lastDescr = '' + } + } + s.push(comments + '\n' + pad + ' public init(' + init + ') {' + code + '\n' + pad + ' }') +} function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { @@ -82,28 +108,29 @@ function handle_config(conf, pre, title, descr) { // handle bindings // generate swift - const swift = config_bindings.swift['Config' + camelCaseUp(pre || '')] + const swift = config_bindings.swift[camelCaseUp(pre || 'In3Config')] + const pad = pre ? ' ' : '' if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) if (typeof c.type === 'object') { - swiftType = 'Config' + camelCaseUp(key) + swiftType = camelCaseUp(key) config_bindings.swift[swiftType] = [ - '/// ' + c.descr.replace(/\n/gm, '\n/// '), - 'public struct ' + swiftType + ' : Codable {' + ' /// ' + c.descr.replace(/\n/gm, '\n/// '), + ' public struct ' + swiftType + ' : Codable {' ] } else if (swiftType == 'Uint') swiftType = 'UInt64' else if (swiftType.startsWith('Byte') || swiftType.startsWith('Address')) swiftType = 'String' if (swiftType.endsWith('[]')) swiftType = '[' + swiftType.substr(0, swiftType.length - 2) + ']' if (c.array) swiftType = '[' + swiftType + ']' - swift.push('\n /// ' + ( + swift.push('\n' + pad + ' /// ' + ( c.descr + (c.default ? ('\n(default: `' + JSON.stringify(c.default) + '`)') : '') + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex).trim()).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') - ).replace(/\n/gm, '\n /// ')) - swift.push(' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) + ).replace(/\n/gm, '\n' + pad + ' /// ')) + swift.push(pad + ' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) } // handle doc if (!pre) { @@ -249,8 +276,11 @@ for (const s of Object.keys(docs).sort()) { } handle_config(config, '') +Object.keys(config_bindings.swift).forEach(_ => createSwiftInitForStruct(config_bindings.swift[_], _ == 'In3Config' ? '' : ' ')) fs.writeFileSync('../swift/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( - Object.keys(config_bindings.swift).map(type => config_bindings.swift[type].join('\n') + '\n}\n\n').join('') + config_bindings.swift.In3Config.join('\n') + '\n\n' + + Object.keys(config_bindings.swift).filter(_ => _ != 'In3Config').map(type => config_bindings.swift[type].join('\n') + '\n }\n\n').join('') + + '\n}\n' ), { encoding: 'utf8' }) diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift index 7c74c2454..0ee0d9545 100644 --- a/swift/Sources/In3/API/Eth.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -1,16 +1,23 @@ import Foundation +/// Ethereum API +/// a collection of ethereum-specific functions. public class Eth { internal var in3: In3; - + + /// initializer with Incubed client init(_ in3:In3) { self.in3 = in3 } + /// returns the current blockNumber public func blockNumber() -> Future { return execAndConvert(in3: in3, method:"eth_blockNumber", convertWith: toUInt64) } - + + /// returns the TransactionReceipt for the given transsaction hash + /// - Paramater hash : the transaction hash + /// the result is an optional value depending on the existence of such a Receipt. public func getTransactionReceipt(hash:String) -> Future { return execAndConvertOptional(in3: in3, method:"eth_getTransactionReceipt", params:RPCObject(hash),convertWith: { try EthTransactionReceipt($0,$1) } ) } @@ -18,10 +25,13 @@ public class Eth { } +/// a TransactionReceipt public struct EthTransactionReceipt { + + /// the transactionhash public var hash: String - public init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc) else { return nil } diff --git a/swift/Sources/In3/Config.swift b/swift/Sources/In3/Config.swift index dce292f8a..991536e15 100644 --- a/swift/Sources/In3/Config.swift +++ b/swift/Sources/In3/Config.swift @@ -3,7 +3,13 @@ import Foundation /// The main Incubed Configuration -public struct Config : Codable { +public struct In3Config : Codable { + + /// create a new Incubed Client based on the Configuration + public func createClient() throws -> In3 { + return try In3(self) + } + /// the chainId or the name of a known chain. It defines the nodelist to connect to. /// (default: `"mainnet"`) @@ -129,7 +135,7 @@ public struct Config : Codable { /// - address: "0x45d45e6ff99e6c34a235d263965910298985fcfe" /// url: https://in3-v2.slock.it/mainnet/nd-1 /// props: "0xFFFF"` - public var nodes : ConfigNodes? + public var nodes : Nodes? /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). /// @@ -153,7 +159,7 @@ public struct Config : Codable { /// - null /// - https://approver.service.com /// ``` - public var zksync : ConfigZksync? + public var zksync : Zksync? /// the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) /// @@ -172,123 +178,252 @@ public struct Config : Codable { /// /// Example: `maxDAP: 30 /// maxDiff: 5` - public var btc : ConfigBtc? -} - -/// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. -public struct ConfigNodes : Codable { - - /// address of the registry contract. (This is the data-contract!) - public var contract : String - - /// address of the whiteList contract. This cannot be combined with whiteList! - public var whiteListContract : String? - - /// manual whitelist. - public var whiteList : String? - - /// identifier of the registry. - public var registryId : String - - /// if set, the nodeList will be updated before next request. - public var needsUpdate : Bool? + public var btc : Btc? + + /// initialize it memberwise + /// - Parameter chainId : the chainId or the name of a known chain. It defines the nodelist to connect to. + /// - Parameter finality : the number in percent needed in order reach finality (% of signature of the validators). + /// - Parameter includeCode : if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. + /// - Parameter maxAttempts : max number of attempts in case a response is rejected. + /// - Parameter keepIn3 : if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. + /// - Parameter stats : if true, requests sent will be used for stats. + /// - Parameter useBinary : if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. + /// - Parameter experimental : iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. + /// - Parameter timeout : specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. + /// - Parameter proof : if true the nodes should send a proof of the response. If set to none, verification is turned off completly. + /// - Parameter replaceLatestBlock : if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. + /// - Parameter autoUpdateList : if true the nodelist will be automaticly updated if the lastBlock is newer. + /// - Parameter signatureCount : number of signatures requested in order to verify the blockhash. + /// - Parameter bootWeights : if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. + /// - Parameter useHttp : if true the client will try to use http instead of https. + /// - Parameter minDeposit : min stake of the server. Only nodes owning at least this amount will be chosen. + /// - Parameter nodeProps : used to identify the capabilities of the node. + /// - Parameter requestCount : the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. + /// - Parameter rpc : url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. + /// - Parameter nodes : defining the nodelist. collection of JSON objects with chain Id (hex string) as key. + /// - Parameter zksync : configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + /// - Parameter key : the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + /// - Parameter pk : registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) + /// - Parameter btc : configure the Bitcoin verification + public init(chainId : String? = nil, finality : UInt64? = nil, includeCode : Bool? = nil, maxAttempts : UInt64? = nil, keepIn3 : Bool? = nil, stats : Bool? = nil, useBinary : Bool? = nil, experimental : Bool? = nil, timeout : UInt64? = nil, proof : String? = nil, replaceLatestBlock : UInt64? = nil, autoUpdateList : Bool? = nil, signatureCount : UInt64? = nil, bootWeights : Bool? = nil, useHttp : Bool? = nil, minDeposit : UInt64? = nil, nodeProps : UInt64? = nil, requestCount : UInt64? = nil, rpc : String? = nil, nodes : Nodes? = nil, zksync : Zksync? = nil, key : String? = nil, pk : String? = nil, btc : Btc? = nil) { + self.chainId = chainId + self.finality = finality + self.includeCode = includeCode + self.maxAttempts = maxAttempts + self.keepIn3 = keepIn3 + self.stats = stats + self.useBinary = useBinary + self.experimental = experimental + self.timeout = timeout + self.proof = proof + self.replaceLatestBlock = replaceLatestBlock + self.autoUpdateList = autoUpdateList + self.signatureCount = signatureCount + self.bootWeights = bootWeights + self.useHttp = useHttp + self.minDeposit = minDeposit + self.nodeProps = nodeProps + self.requestCount = requestCount + self.rpc = rpc + self.nodes = nodes + self.zksync = zksync + self.key = key + self.pk = pk + self.btc = btc + } - /// average block time (seconds) for this chain. - public var avgBlockTime : UInt64? + /// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. + public struct Nodes : Codable { + + /// address of the registry contract. (This is the data-contract!) + public var contract : String + + /// address of the whiteList contract. This cannot be combined with whiteList! + public var whiteListContract : String? + + /// manual whitelist. + public var whiteList : String? + + /// identifier of the registry. + public var registryId : String + + /// if set, the nodeList will be updated before next request. + public var needsUpdate : Bool? + + /// average block time (seconds) for this chain. + public var avgBlockTime : UInt64? + + /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. + public var verifiedHashes : [VerifiedHashes]? + + /// manual nodeList. As Value a array of Node-Definitions is expected. + public var nodeList : [NodeList]? + + /// initialize it memberwise + /// - Parameter contract : defining the nodelist. collection of JSON objects with chain Id (hex string) as key. + /// - Parameter whiteListContract : address of the whiteList contract. This cannot be combined with whiteList! + /// - Parameter whiteList : manual whitelist. + /// - Parameter registryId : identifier of the registry. + /// - Parameter needsUpdate : if set, the nodeList will be updated before next request. + /// - Parameter avgBlockTime : average block time (seconds) for this chain. + /// - Parameter verifiedHashes : if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. + /// - Parameter nodeList : manual nodeList. As Value a array of Node-Definitions is expected. + public init(contract : String, whiteListContract : String? = nil, whiteList : String? = nil, registryId : String, needsUpdate : Bool? = nil, avgBlockTime : UInt64? = nil, verifiedHashes : [VerifiedHashes]? = nil, nodeList : [NodeList]? = nil) { + self.contract = contract + self.whiteListContract = whiteListContract + self.whiteList = whiteList + self.registryId = registryId + self.needsUpdate = needsUpdate + self.avgBlockTime = avgBlockTime + self.verifiedHashes = verifiedHashes + self.nodeList = nodeList + } + } /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. - public var verifiedHashes : [ConfigVerifiedHashes]? - - /// manual nodeList. As Value a array of Node-Definitions is expected. - public var nodeList : [ConfigNodeList]? -} - -/// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. -public struct ConfigVerifiedHashes : Codable { - - /// block number - public var block : UInt64 - - /// verified hash corresponding to block number. - public var hash : String -} + public struct VerifiedHashes : Codable { -/// manual nodeList. As Value a array of Node-Definitions is expected. -public struct ConfigNodeList : Codable { + /// block number + public var block : UInt64 - /// URL of the node. - public var url : String + /// verified hash corresponding to block number. + public var hash : String - /// address of the node - public var address : String + /// initialize it memberwise + /// - Parameter block : if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. + /// - Parameter hash : verified hash corresponding to block number. + public init(block : UInt64, hash : String) { + self.block = block + self.hash = hash + } + } - /// used to identify the capabilities of the node (defaults to 0xFFFF). - public var props : UInt64 -} - -/// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). -public struct ConfigZksync : Codable { - - /// url of the zksync-server (if not defined it will be choosen depending on the chain) - /// (default: `"https://api.zksync.io/jsrpc"`) - public var provider_url : String? - - /// the account to be used. if not specified, the first signer will be used. - public var account : String? + /// manual nodeList. As Value a array of Node-Definitions is expected. + public struct NodeList : Codable { - /// the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. - public var sync_key : String? + /// URL of the node. + public var url : String - /// address of the main contract- If not specified it will be taken from the server. - public var main_contract : String? + /// address of the node + public var address : String - /// type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. - /// (default: `"pk"`) - /// - /// Possible Values are: - /// - /// - `pk` : Private matching the account is used ( for EOA) - /// - `contract` : Contract Signature based EIP 1271 - /// - `create2` : create2 optionas are used - /// - public var signer_type : String? + /// used to identify the capabilities of the node (defaults to 0xFFFF). + public var props : UInt64 - /// concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. - public var musig_pub_keys : String? + /// initialize it memberwise + /// - Parameter url : manual nodeList. As Value a array of Node-Definitions is expected. + /// - Parameter address : address of the node + /// - Parameter props : used to identify the capabilities of the node (defaults to 0xFFFF). + public init(url : String, address : String, props : UInt64) { + self.url = url + self.address = address + self.props = props + } + } - /// a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. - public var musig_urls : [String]? + /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + public struct Zksync : Codable { + + /// url of the zksync-server (if not defined it will be choosen depending on the chain) + /// (default: `"https://api.zksync.io/jsrpc"`) + public var provider_url : String? + + /// the account to be used. if not specified, the first signer will be used. + public var account : String? + + /// the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. + public var sync_key : String? + + /// address of the main contract- If not specified it will be taken from the server. + public var main_contract : String? + + /// type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. + /// (default: `"pk"`) + /// + /// Possible Values are: + /// + /// - `pk` : Private matching the account is used ( for EOA) + /// - `contract` : Contract Signature based EIP 1271 + /// - `create2` : create2 optionas are used + /// + public var signer_type : String? + + /// concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. + public var musig_pub_keys : String? + + /// a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. + public var musig_urls : [String]? + + /// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + public var create2 : Create2? + + /// initialize it memberwise + /// - Parameter provider_url : configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). + /// - Parameter account : the account to be used. if not specified, the first signer will be used. + /// - Parameter sync_key : the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. + /// - Parameter main_contract : address of the main contract- If not specified it will be taken from the server. + /// - Parameter signer_type : type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. + /// - Parameter musig_pub_keys : concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. + /// - Parameter musig_urls : a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. + /// - Parameter create2 : create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + public init(provider_url : String? = nil, account : String? = nil, sync_key : String? = nil, main_contract : String? = nil, signer_type : String? = nil, musig_pub_keys : String? = nil, musig_urls : [String]? = nil, create2 : Create2? = nil) { + self.provider_url = provider_url + self.account = account + self.sync_key = sync_key + self.main_contract = main_contract + self.signer_type = signer_type + self.musig_pub_keys = musig_pub_keys + self.musig_urls = musig_urls + self.create2 = create2 + } + } /// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. - public var create2 : ConfigCreate2? -} + public struct Create2 : Codable { -/// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. -public struct ConfigCreate2 : Codable { + /// The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory ) + public var creator : String - /// The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory ) - public var creator : String + /// a salt-argument, which will be added to the pubkeyhash and create the create2-salt. + public var saltarg : String - /// a salt-argument, which will be added to the pubkeyhash and create the create2-salt. - public var saltarg : String + /// the hash of the actual deploy-tx including the constructor-arguments. + public var codehash : String - /// the hash of the actual deploy-tx including the constructor-arguments. - public var codehash : String -} + /// initialize it memberwise + /// - Parameter creator : create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. + /// - Parameter saltarg : a salt-argument, which will be added to the pubkeyhash and create the create2-salt. + /// - Parameter codehash : the hash of the actual deploy-tx including the constructor-arguments. + public init(creator : String, saltarg : String, codehash : String) { + self.creator = creator + self.saltarg = saltarg + self.codehash = codehash + } + } -/// configure the Bitcoin verification -public struct ConfigBtc : Codable { + /// configure the Bitcoin verification + public struct Btc : Codable { + + /// max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. + /// (default: `20`) + /// + /// Example: `10` + public var maxDAP : UInt64? + + /// max increase (in percent) of the difference between targets when accepting new targets. + /// (default: `10`) + /// + /// Example: `5` + public var maxDiff : UInt64? + + /// initialize it memberwise + /// - Parameter maxDAP : configure the Bitcoin verification + /// - Parameter maxDiff : max increase (in percent) of the difference between targets when accepting new targets. + public init(maxDAP : UInt64? = nil, maxDiff : UInt64? = nil) { + self.maxDAP = maxDAP + self.maxDiff = maxDiff + } + } - /// max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. - /// (default: `20`) - /// - /// Example: `10` - public var maxDAP : UInt64? - /// max increase (in percent) of the difference between targets when accepting new targets. - /// (default: `10`) - /// - /// Example: `5` - public var maxDiff : UInt64? } - diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 29f8e097a..80958a714 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -16,7 +16,7 @@ public class In3 { } } - public init(_ config: Config) throws { + public init(_ config: In3Config) throws { transport = httpTransfer in3 = in3_for_chain_auto_init(1) try configure(config) @@ -27,7 +27,7 @@ public class In3 { in3_free(in3) } - public func configure(_ config: Config) throws { + public func configure(_ config: In3Config) throws { let jsonConfig = try JSONEncoder().encode(config) let error = in3_configure(in3, String(decoding: jsonConfig, as: UTF8.self)) if let msg = error { diff --git a/swift/Sources/In3/Utils/Cache.swift b/swift/Sources/In3/Utils/Cache.swift index 958c0409f..ca59dd32a 100644 --- a/swift/Sources/In3/Utils/Cache.swift +++ b/swift/Sources/In3/Utils/Cache.swift @@ -1,28 +1,43 @@ import Foundation import CIn3 +/// Protocol for Cache-Implementation. +/// The cache is used to store data like nodelists and their reputations, contract codes and more. +/// those calls a synchronous calls and should be fast. +/// in order to set the cache, use the `In3.cache`-property. public protocol In3Cache { + + /// find the data for the given cache-key or `nil`if not found. func getEntry(key:String)->Data? + + /// write the data to the cache using the given key.. func setEntry(key:String,value:Data)->Void + + /// clears all cache entries func clear()->Void } - +/// File-Implementation for the cache. public class FileCache : In3Cache { var dir:URL + /// creates the cache-directory in the USers home-directory with hte name `.in3` convenience init() throws { try self.init(URL(fileURLWithPath: ".in3", relativeTo: FileManager.default.homeDirectoryForCurrentUser)) } + + /// caches data in the given directory convenience init(_ dir:String) throws { try self.init(URL(fileURLWithPath: dir, isDirectory: true)) } + /// caches data in the given directory init(_ dir:URL) throws { try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) self.dir = dir } + /// write the data to the cache using the given key.. public func setEntry(key: String, value: Data) { do { try value.write(to: URL(fileURLWithPath: key, relativeTo: dir)) @@ -30,6 +45,7 @@ public class FileCache : In3Cache { } } + /// find the data for the given cache-key or `nil`if not found. public func getEntry(key: String) -> Data? { do { return try Data(contentsOf: URL(fileURLWithPath: key, relativeTo: dir)) @@ -38,6 +54,7 @@ public class FileCache : In3Cache { } } + /// clears all cache entries public func clear() { do { try FileManager.default.removeItem(at: dir) @@ -93,28 +110,5 @@ internal func registerCache(_ in3:In3) { in3_register_swift(in3ptr, &cbs) } - - /* - let callbacks = callbacks( - cl - - printGreeting: { (modifier) in - printGreeting(modifier: modifier) - } - ) - */ -} - -/* - -private func printGreeting(modifier: UnsafePointer) { - print("Hello \(String(cString: modifier))World!") } -var callbacks = SomeCLibCallbacks( - printGreeting: { (modifier) in - printGreeting(modifier: modifier) - } -) -SomeCLibSetup(&callbacks) -*/ diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift index 7fb27fd6b..34be1da38 100644 --- a/swift/Sources/In3/Utils/Convert.swift +++ b/swift/Sources/In3/Utils/Convert.swift @@ -2,7 +2,7 @@ import Foundation - +/// converts a RPC-Object to UInt64 or throws internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt64?{ if let data = data { switch data { @@ -30,6 +30,7 @@ internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt return nil } +/// converts a RPC-Object to Bool or throws internal func toBool(_ data:RPCObject?, _ optional:Bool = true) throws -> Bool?{ if let data = data { switch data { @@ -59,7 +60,7 @@ internal func toBool(_ data:RPCObject?, _ optional:Bool = true) throws -> Bool?{ return nil } - +/// converts a RPC-Object to String or throws internal func toString(_ data:RPCObject?, _ optional:Bool = true) throws -> String?{ if let data = data { switch data { @@ -83,7 +84,7 @@ internal func toString(_ data:RPCObject?, _ optional:Bool = true) throws -> Stri return nil } - +/// converts a RPC-Object to a Dictory or throws internal func toObject(_ data:RPCObject?,_ optional:Bool = true) throws -> [String: RPCObject]?{ if let data = data { switch data { @@ -99,7 +100,7 @@ internal func toObject(_ data:RPCObject?,_ optional:Bool = true) throws -> [Str } - +/// converts a RPC-Object to a List or throws internal func toArray(_ data:RPCObject?, _ optional:Bool = true) throws -> [RPCObject]?{ if let data = data { switch data { @@ -114,7 +115,7 @@ internal func toArray(_ data:RPCObject?, _ optional:Bool = true) throws -> [RPCO return nil } - +/// executes a rpc-request and converts the result as non optional. (will return a rejected promise if it is `nil`) internal func execAndConvert(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { let promise = Promise() do { @@ -140,6 +141,7 @@ internal func execAndConvert(in3:In3, method: String, params: RPCObject.. return promise } +/// executes a rpc-request and converts the result as optional allowing `nil`as valid result. internal func execAndConvertOptional(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { let promise = Promise() do { diff --git a/swift/Sources/In3/Utils/Error.swift b/swift/Sources/In3/Utils/Error.swift index ef39d046d..054b4447a 100644 --- a/swift/Sources/In3/Utils/Error.swift +++ b/swift/Sources/In3/Utils/Error.swift @@ -1,17 +1,36 @@ import Foundation - +/// Base Incubed errors public enum IncubedError: Error { + + /// Configuration Error, which is only thrown within the Config or initializer of the In3 case config(message: String) + + /// error during rpc-execution case rpc(message: String) + + /// error during converting the response to a target case convert(message: String) } +/// the result of a Transport operation. +/// it will only be used internally to report the time and http-status of the response, before verifying the result. public enum TransportResult { + /// successful response + /// - Parameter data : the raw data + /// - Parameter time : the time in milliseconds to execute the request case success(_ data:Data, _ time:Int) + + /// failed response + /// - Parameter msg : the error-message + /// - Parameter httpStatus : the http status code case error(_ msg:String, _ httpStatus:Int) } +/// result of a RPC-Request public enum RequestResult { + /// success full respons with the data as result. case success(_ data:RPCObject) + + /// failed request with the msg describiung the error case error(_ msg:String) } diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index c406d4992..4f18dc3e1 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -250,51 +250,75 @@ internal extension JSONObject { } } +/// Wrapper enum for a rpc-object, which could be different kinds public enum RPCObject: Equatable { + /// a JSON `null` value. case none + + /// a String value case string(String) + + /// a Integer case integer(Int) + + /// a Doucle-Value case double(Double) + + /// a Boolean case bool(Bool) + + /// a Array or List of RPC-Objects case list([RPCObject]) + + /// a JSON-Object represented as Dictionary with properties as keys and their values as RPCObjects case dictionary([String: RPCObject]) + /// Wrap a String as Value public init(_ value: String) { self = .string(value) } + /// Wrap a Integer as Value public init(_ value: Int) { self = .integer(value) } + /// Wrap a Double as Value public init(_ value: Double) { self = .double(value) } + /// Wrap a Bool as Value public init(_ value: Bool) { self = .bool(value) } + /// Wrap a String -Array as Value public init(_ value: [String]) { self = .list(value.map { RPCObject($0) }) } + /// Wrap a Integer -Array as Value public init(_ value: [Int]) { self = .list(value.map { RPCObject($0) }) } + /// Wrap a Object with String values as Value public init(_ value: [String: String]) { self = .dictionary(value.mapValues { RPCObject($0) }) } + /// Wrap a Object with Integer values as Value public init(_ value: [String: Int]) { self = .dictionary(value.mapValues { RPCObject($0) }) } + /// Wrap a Object with RPCObject values as Value public init(_ value: [String: RPCObject]) { self = .dictionary(value) } + /// Wrap a Array or List of RPCObjects as Value public init(_ value: [RPCObject]) { self = .list(value) } @@ -319,19 +343,29 @@ public enum RPCObject: Equatable { } } +/// Error of a RPC-Request public struct RPCError { + /// initializer public init(_ kind: Kind, description: String? = nil) { self.kind = kind self.description = description } + /// the error-type public let kind: Kind + + /// the error description public let description: String? + /// the error type public enum Kind { + /// invalid Method case invalidMethod + /// invalid Params case invalidParams(String) + /// invalid Request case invalidRequest(String) + /// application Error case applicationError(String) } } diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 798a8b691..9c114595c 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -4,7 +4,7 @@ import Foundation final class In3Tests: XCTestCase { func testLocal() throws { - let in3 = try In3(Config(chainId: "mainnet")) + let in3 = try In3(In3Config(chainId: "mainnet")) let hash = try in3.execLocal("keccak",RPCObject("simon")) switch hash { case let .string(value): @@ -15,14 +15,14 @@ final class In3Tests: XCTestCase { } func testJSON() throws { - let in3 = try In3(Config(chainId: "mainnet")) + let in3 = try In3(In3Config(chainId: "mainnet")) let res = in3.executeJSON("{\"method\":\"keccak\",\"params\":[\"simon\"]}") XCTAssertEqual(res , "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a\"}") } func testExec() throws { let expect = XCTestExpectation(description: "Should get a hash-value") - let in3 = try In3(Config(chainId: "mainnet")) + let in3 = try In3(In3Config(chainId: "mainnet")) try in3.exec("keccak", RPCObject("simon"), cb: { switch $0 { case let .error(msg): @@ -44,7 +44,7 @@ final class In3Tests: XCTestCase { func testAPI() throws { let expect = XCTestExpectation(description: "Should get a hash-value") // let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) - let in3 = try In3(Config(chainId: "mainnet")) + let in3 = try In3(In3Config(chainId: "mainnet")) Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { switch $0 { case let .failure(err): diff --git a/swift/Tests/In3Tests/Mock.swift b/swift/Tests/In3Tests/Mock.swift new file mode 100644 index 000000000..78015b0a2 --- /dev/null +++ b/swift/Tests/In3Tests/Mock.swift @@ -0,0 +1,10 @@ + +import XCTest +import Foundation +import In3 + +internal func createIn3(mockdata:[String:String]) throws -> In3 { +// let in1 = try In3(In3Config(chainId: "mainnet")) + let in3 = try In3Config(chainId: "mainnet").createClient() + return in3 +} diff --git a/swift/docs/1_intro.md b/swift/docs/1_intro.md index eae6f2ce7..034747f5d 100644 --- a/swift/docs/1_intro.md +++ b/swift/docs/1_intro.md @@ -1,12 +1,37 @@ # API Reference Swift -The swift binding contains binaries are only available for macos and ios. +The swift binding contains binaries are only available for macos and ios. ( for now) ## Install TODO +## Usage + +In order to use incubed, you need to add the In3-Package as dependency and import into your code: + +```swift +import In3 + +// configure and create a client. +let in3 = try In3Config(chainId: "mainnet", requestCount:1).createClient() + +// use the Eth-Api to execute requests +Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0").observe(using: { + switch $0 { + case let .failure(err): + print("Failed to get the tx : \(err)") + case let .success( tx ): + if let tx = tx { + print("Found tx with txhash \(tx.hash)") + } else { + print("Tx does not exist") + } + } + }) +``` + ## Classes From b174ff8152e73d1c68a8b537c2e5f244e75a50f2 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Apr 2021 17:32:59 +0200 Subject: [PATCH 100/221] fixed review comments --- swift/Sources/In3/API/Eth.swift | 2 +- swift/Sources/In3/In3.swift | 2 +- swift/Sources/In3/Utils/Cache.swift | 37 ++++++++--------------------- 3 files changed, 12 insertions(+), 29 deletions(-) diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift index 0ee0d9545..ca1160b14 100644 --- a/swift/Sources/In3/API/Eth.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -3,7 +3,7 @@ import Foundation /// Ethereum API /// a collection of ethereum-specific functions. public class Eth { - internal var in3: In3; + internal var in3: In3 /// initializer with Incubed client init(_ in3:In3) { diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 80958a714..b8e2e7d95 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -20,7 +20,7 @@ public class In3 { transport = httpTransfer in3 = in3_for_chain_auto_init(1) try configure(config) - registerCache(self) + try registerCache(self) } deinit { diff --git a/swift/Sources/In3/Utils/Cache.swift b/swift/Sources/In3/Utils/Cache.swift index ca59dd32a..55bf0a5e3 100644 --- a/swift/Sources/In3/Utils/Cache.swift +++ b/swift/Sources/In3/Utils/Cache.swift @@ -39,47 +39,32 @@ public class FileCache : In3Cache { /// write the data to the cache using the given key.. public func setEntry(key: String, value: Data) { - do { - try value.write(to: URL(fileURLWithPath: key, relativeTo: dir)) - } catch { - } + try? value.write(to: URL(fileURLWithPath: key, relativeTo: dir)) } /// find the data for the given cache-key or `nil`if not found. public func getEntry(key: String) -> Data? { - do { - return try Data(contentsOf: URL(fileURLWithPath: key, relativeTo: dir)) - } catch { - return nil - } + return try? Data(contentsOf: URL(fileURLWithPath: key, relativeTo: dir)) } /// clears all cache entries public func clear() { - do { - try FileManager.default.removeItem(at: dir) - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) - } catch { - } + try? FileManager.default.removeItem(at: dir) + try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) } } internal var defaultCache:In3Cache? -internal func registerCache(_ in3:In3) { +internal func registerCache(_ in3:In3) throws { if defaultCache == nil { - do { - defaultCache = try FileCache() - } catch { - print("Could not init the cache : \(error)") - } + defaultCache = try FileCache() } var cbs = swift_cb_t( cache_get: { ctx -> in3_ret_t in - if let cache = defaultCache { - let key = String(cString: ctx.pointee.key) - let value = cache.getEntry(key: key) - if let data = value { + let key = String(cString: ctx.pointee.key) + if let cache = defaultCache, + let data = cache.getEntry(key: key) { data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer ) in ctx.pointee.content = b_new(ptr.baseAddress?.assumingMemoryBound(to: UInt8.self), UInt32(data.count)) } @@ -87,12 +72,10 @@ internal func registerCache(_ in3:In3) { } else { return IN3_EIGNORE } - } - return IN3_OK }, cache_set: { ctx -> in3_ret_t in + let key = String(cString: ctx.pointee.key) if let cache = defaultCache { - let key = String(cString: ctx.pointee.key) cache.setEntry(key: key, value: Data(bytes: ctx.pointee.content.pointee.data, count: Int(ctx.pointee.content.pointee.len))) return IN3_OK } From 1f4a9b0ea3a3bf626c25f6edad267b334b70da31 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:07:13 +0200 Subject: [PATCH 101/221] fix rpc result-definitions --- c/src/api/eth1/rpc.yml | 71 +++--- c/src/api/eth1/rpc_api.c | 19 +- c/src/cmd/in3/args.h | 2 +- c/src/core/client/rpc.yml | 3 +- c/src/nodeselect/full/rpc.yml | 11 +- c/src/pay/zksync/rpc.yml | 56 +++-- c/src/signer/pk-signer/rpc.yml | 4 +- c/src/verifier/btc/rpc.yml | 356 +++++++++++++++++++++--------- c/src/verifier/eth1/basic/rpc.yml | 107 +++++++-- c/src/verifier/eth1/full/rpc.yml | 4 +- c/src/verifier/eth1/nano/rpc.yml | 3 +- c/src/verifier/ipfs/rpc.yml | 6 +- swift/Sources/In3/API/Eth.swift | 41 ---- 13 files changed, 436 insertions(+), 247 deletions(-) delete mode 100644 swift/Sources/In3/API/Eth.swift diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 7a4acbdc4..e0708cd33 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -33,15 +33,17 @@ types: in3: in3_abiEncode: + sync: true descr: based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. params: signature: type: string descr: the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. params: - type: array + type: any + array: true descr: a array of arguments. the number of arguments must match the arguments in the signature. - returns: + result: type: hex descr: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. example: @@ -51,6 +53,7 @@ in3: response: "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" in3_abiDecode: + sync: true descr: based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. params: signature: @@ -59,9 +62,10 @@ in3: data: type: hex descr: the data to decode (usually the result of a eth_call) - returns: - type: array - descr: a array (if more then one arguments in the result-type) or the the value after decodeing. + result: + type: any + array: true + descr: a array with the values after decodeing. example: request: - (address,uint256) @@ -71,6 +75,7 @@ in3: - "0x05" in3_checksumAddress: + sync: true descr: Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) params: address: @@ -80,7 +85,7 @@ in3: descr: if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) type: bool optional: true - returns: + result: descr: the address-string using the upper/lowercase hex characters. example: request: @@ -103,7 +108,7 @@ in3: type: string optional: true default: addr - returns: + result: descr: the value of the specified field example: request: @@ -115,18 +120,19 @@ in3: in3_toWei: + sync : true descr: converts the given value into wei. params: value: descr: the value, which may be floating number as string - type: string or uint + type: string | uint example: "0.9" unit: descr: the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` type: string optional: true default: eth - returns: + result: descr: the value in wei as hex. example: request: @@ -136,11 +142,12 @@ in3: in3_fromWei: + sync: true descr: converts a given uint (also as hex) with a wei-value into a specified unit. params: value: descr: the value in wei - type: uint or bytes + type: bytes | uint example: "0x234324abdef" unit: descr: the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` @@ -149,7 +156,7 @@ in3: descr: fix number of digits after the comma. If left out, only as many as needed will be included. type: uint optional: true - returns: + result: descr: the value as string. example: request: @@ -159,12 +166,13 @@ in3: response: "0.158" in3_pk2address: + sync: true descr: extracts the address from a private key. params: pk: descr: the 32 bytes private key as hex. type: bytes32 - returns: + result: descr: the address example: request: @@ -172,12 +180,13 @@ in3: response: "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" in3_pk2public: + sync: true descr: extracts the public key from a private key. params: pk: descr: the 32 bytes private key as hex. type: bytes32 - returns: + result: descr: the public key as 64 bytes example: request: @@ -185,6 +194,7 @@ in3: response: "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f78186577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" in3_ecrecover: + sync: true descr: extracts the public key and address from signature. params: msg: @@ -198,7 +208,7 @@ in3: type: string default: raw optional: true - returns: + result: descr: the extracted public key and address type: publicKey: @@ -224,7 +234,7 @@ in3: descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). type: transaction - returns: + result: descr: the unsigned raw transaction as hex. example: request: @@ -243,7 +253,7 @@ in3: descr: the account to sign type: address - returns: + result: descr: the raw transaction with signature. example: request: @@ -266,7 +276,7 @@ in3: default: raw optional: true - returns: + result: descr: the signature type: message: @@ -302,16 +312,17 @@ in3: v: 27 in3_decryptKey: + sync: true descr: decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. params: key: descr: Keydata as object as defined in the keystorefile - type: object + type: string passphrase: descr: the password to decrypt it. type: string - returns: + result: descr: a raw private key (32 bytes) example: request: @@ -334,8 +345,9 @@ in3: response: "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" in3_cacheClear: + sync: true descr: clears the incubed cache (usually found in the .in3-folder) - returns: + result: descr: true indicating the success example: request: [] @@ -345,13 +357,15 @@ eth: web3_clientVersion: descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. - returns: + result: descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. keccak: + sync: true alias: web3_sha3 web3_sha3: + sync: true descr: | Returns Keccak-256 (not the standardized SHA3-256) of the given data. @@ -362,7 +376,7 @@ eth: data: descr: data to hash type: bytes - returns: + result: descr: the 32byte hash of the data example: request: @@ -370,6 +384,7 @@ eth: response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" sha256: + sync: true descr: | Returns sha-256 of the given data. @@ -378,7 +393,7 @@ eth: data: descr: data to hash type: bytes - returns: + result: descr: the 32byte hash of the data example: request: @@ -386,11 +401,13 @@ eth: response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" net_version: + sync: true descr: the Network Version (currently 1) - returns: + result: descr: the Version number in3_createKey: + sync: true descr: | Generates 32 random bytes. If /dev/urandom is available it will be used and should generate a secure random number. @@ -400,7 +417,7 @@ eth: optional: true descr: the seed. If given the result will be deterministic. type: bytes - returns: + result: descr: the 32byte random data example: request: [] @@ -424,7 +441,7 @@ eth: message: descr: the message to sign type: bytes - returns: + result: descr: the signature (65 bytes) for the given message. example: request: @@ -440,7 +457,7 @@ eth: tx: descr: transaction to sign type: transaction - returns: + result: descr: the raw signed transaction example: request: diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 5fae18d9c..052cb7580 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -518,16 +518,27 @@ static in3_ret_t in3_cacheClear(in3_rpc_handle_ctx_t* ctx) { } static in3_ret_t in3_decryptKey(in3_rpc_handle_ctx_t* ctx) { - d_token_t* keyfile = d_get_at(ctx->params, 0); - bytes_t password_bytes = d_to_bytes(d_get_at(ctx->params, 1)); - bytes32_t dst; + d_token_t* keyfile = d_get_at(ctx->params, 0); + bytes_t password_bytes = d_to_bytes(d_get_at(ctx->params, 1)); + bytes32_t dst; + json_ctx_t* sctx = NULL; if (!password_bytes.data) return req_set_error(ctx->req, "you need to specify a passphrase", IN3_EINVAL); - if (!keyfile || d_type(keyfile) != T_OBJECT) return req_set_error(ctx->req, "no valid key given", IN3_EINVAL); + if (d_type(keyfile) == T_STRING) { + sctx = parse_json(d_string(keyfile)); + if (!sctx) return req_set_error(ctx->req, "invalid keystore-json", IN3_EINVAL); + keyfile = sctx->result; + } + + if (!keyfile || d_type(keyfile) != T_OBJECT) { + if (sctx) json_free(sctx); + return req_set_error(ctx->req, "no valid key given", IN3_EINVAL); + } char* passphrase = alloca(password_bytes.len + 1); memcpy(passphrase, password_bytes.data, password_bytes.len); passphrase[password_bytes.len] = 0; in3_ret_t res = decrypt_key(keyfile, passphrase, dst); + if (sctx) json_free(sctx); if (res) return req_set_error(ctx->req, "Invalid key", res); return in3_rpc_handle_with_bytes(ctx, bytes(dst, 32)); } diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 534eb5ab3..53c560f3c 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,7 +2,7 @@ #include -const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index 080c3c148..c847373fa 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -107,12 +107,13 @@ in3: # rpc-commands in3_config: + skipApi: true descr: changes the configuration of a client. The configuration is passed as the first param and may contain only the values to change. params: config: descr: a Object with config-params. - returns: + result: descr: an boolean confirming that the config has changed. example: request: diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 492ecd7d1..c4738c8ee 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -138,10 +138,11 @@ in3: optional: true addresses: descr: a optional array of addresses of signers the nodeList must include. - type: address[] + array: true + type: address optional: true - returns: + result: descr: the current nodelist type: nodes: @@ -358,7 +359,7 @@ in3: type: bytes32 optional: true - returns: + result: descr: the Array with signatures of all the requires blocks. type: blockHash: @@ -369,7 +370,7 @@ in3: type: uint r: descr: r-value of the signature - type: bytres32 + type: bytes32 s: descr: s-value of the signature type: bytes32 @@ -396,7 +397,7 @@ in3: address: descr: address of whitelist contract type: address - returns: + result: descr: the whitelisted addresses type: nodes: diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 6f0b5b108..a8299e805 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -99,7 +99,7 @@ zksync: # rpc zksync_contract_address: descr: returns the contract address - returns: + result: descr: fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. type: govContract: @@ -117,7 +117,7 @@ zksync: zksync_tokens: descr: returns the list of all available tokens - returns: + result: descr: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. type: address: @@ -163,7 +163,7 @@ zksync: descr: the account-address. if not specified, the client will try to use its own address based on the signer config. type: address optional: true - returns: + result: descr: the current state of the requested account. type: address: @@ -173,11 +173,9 @@ zksync: descr: the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. type: balances: - descr: the token-balances. - type: - : - descr: the balance of the token - type: uint + descr: the token-balance + key: the token + type: uint nonce: descr: the nonce or transaction count. type: uint @@ -189,10 +187,8 @@ zksync: type: balances: descr: the token-values. - type: - : - descr: the value of the token - type: uint + key: the token + type: uint id: descr: the assigned id of the account, which will be used when encoding it into the rollup. type: uint @@ -201,10 +197,8 @@ zksync: type: balances: descr: the token-balances. - type: - : - descr: the balance of the token - type: uint + key: the token + type: uint nonce: descr: the nonce or transaction count. type: uint @@ -234,7 +228,7 @@ zksync: tx: descr: the txHash of the send tx type: bytes32 - returns: + result: descr: the current state of the requested tx. type: block: @@ -281,7 +275,7 @@ zksync: token: descr: the token to pay the gas (either the symbol or the address) type: string - returns: + result: descr: the pubKeyHash, if it was executed successfully type: address example: @@ -297,7 +291,7 @@ zksync: descr: the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) type: bytes32 optional: true - returns: + result: descr: the pubKeyHash type: address example: @@ -310,7 +304,7 @@ zksync: returns the current packed PubKey based on the config set. If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. - returns: + result: descr: the pubKey type: bytes32 example: @@ -321,7 +315,7 @@ zksync: zksync_account_address: descr: returns the address of the account used. - returns: + result: descr: the account used. type: address example: @@ -342,7 +336,7 @@ zksync: message: descr: the message to sign type: bytes - returns: + result: descr: | The return value are 96 bytes of signature: - `[0...32]` packed public key @@ -368,7 +362,7 @@ zksync: signature: descr: the signature (96 bytes) type: bytes96 - returns: + result: descr: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. type: uint example: @@ -391,7 +385,7 @@ zksync: token: descr: Symbol or address of the token type: string - returns: + result: descr: the token price type: float example: @@ -412,7 +406,7 @@ zksync: token: descr: the symbol or address of the token to pay type: string - returns: + result: descr: the fees split up into single values type: feeType: @@ -449,7 +443,7 @@ zksync: zksync_sync_key: descr: returns private key used for signing zksync-transactions - returns: + result: descr: the raw private key configured based on the signers seed example: cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c @@ -472,7 +466,7 @@ zksync: descr: address of the account to send the tx from. if not specified, the first available signer will be used. type: address optional: true - returns: + result: descr: the opId. You can use `zksync_ethop_info` to follow the state-changes. type: uint example: @@ -498,7 +492,7 @@ zksync: descr: address of the account to send the tx from. if not specified, the first available signer will be used. type: address optional: true - returns: + result: descr: the transactionHash. use `zksync_tx_info` to check the progress. type: bytes32 example: @@ -525,7 +519,7 @@ zksync: descr: address of the account to send the tx from. if not specified, the first available signer will be used. type: address optional: true - returns: + result: descr: the transactionHash. use `zksync_tx_info` to check the progress. type: bytes32 example: @@ -542,7 +536,7 @@ zksync: token: descr: the token as symbol or address type: string - returns: + result: descr: the transactionReceipt type: transactionReceipt example: @@ -582,7 +576,7 @@ zksync: pubkeys: descr: concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` type: bytes - returns: + result: descr: the compact public Key type: bytes32 example: diff --git a/c/src/signer/pk-signer/rpc.yml b/c/src/signer/pk-signer/rpc.yml index 3e1cc28df..34d51cd43 100644 --- a/c/src/signer/pk-signer/rpc.yml +++ b/c/src/signer/pk-signer/rpc.yml @@ -24,7 +24,7 @@ in3: pk: descr: the 32byte long private key as hex string. type: bytes32 - returns: + result: descr: the address of given key. type: address example: @@ -34,7 +34,7 @@ in3: eth_accounts: descr: returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. - returns: + result: descr: the array of addresses of all registered signers. example: response: diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index d65c3ddaf..c5807b79b 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -1,4 +1,51 @@ types: + btcblockheader: + hash: + descr: the block hash (same as provided) + type: bytes32 + confirmations: + descr: The number of confirmations, or -1 if the block is not on the main chain + type: int + height: + descr: The block height or index + type: uint + version: + descr: The block version + type: uint + versionHex: + descr: The block version formatted in hexadecimal + type: hex + merkleroot: + descr: The merkle root ( 32 bytes ) + type: bytes32 + time: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + mediantime: + descr: The median block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + nonce: + descr: The nonce + type: uint + bits: + descr: The bits ( 4 bytes as hex) representing the target + type: bytes4 + difficulty: + descr: The difficulty + type: uint + chainwork: + descr: Expected number of hashes required to produce the current chain (in hex) + type: uint + nTx: + descr: The number of transactions in the block. + type: uint + previousblockhash: + descr: The hash of the previous block + type: bytes32 + nextblockhash: + descr: The hash of the next block + type: bytes32 + btctransaction: txid: descr: txid @@ -29,6 +76,7 @@ types: type: uint vin: descr: array of json objects of incoming txs to be used + array: true type: txid: descr: the transaction id @@ -49,10 +97,12 @@ types: descr: The script sequence number type: uint txinwitness: + array: true descr: hex-encoded witness data (if any) - type: string[] + type: string vout: descr: array of json objects describing the tx outputs + array: true type: value: descr: The Value in BTC @@ -77,13 +127,14 @@ types: type: string addresses: descr: Array of address(each representing a bitcoin adress) - type: string[] + array: true + type: string blockhash: descr: the block hash type: bytes32 confirmations: descr: The confirmations - type: uint + type: int blocktime: descr: The block time in seconds since epoch (Jan 1 1970 GMT) type: uint @@ -91,6 +142,108 @@ types: descr: Same as "blocktime" type: uint + btcblockWithTx: + hash: + descr: the block hash (same as provided) + type: bytes32 + confirmations: + descr: The number of confirmations, or -1 if the block is not on the main chain + type: int + height: + descr: The block height or index + type: uint + version: + descr: The block version + type: uint + versionHex: + descr: The block version formatted in hexadecimal + type: hex + merkleroot: + descr: The merkle root ( 32 bytes ) + type: bytes32 + time: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + mediantime: + descr: The median block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + nonce: + descr: The nonce + type: uint + bits: + descr: The bits ( 4 bytes as hex) representing the target + type: bytes4 + difficulty: + descr: The difficulty + type: uint + chainwork: + descr: Expected number of hashes required to produce the current chain (in hex) + type: uint + nTx: + descr: The number of transactions in the block. + type: uint + tx: + descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + array: true + type: btctransaction + previousblockhash: + descr: The hash of the previous block + type: bytes32 + nextblockhash: + descr: The hash of the next block + type: bytes32 + + btcblock: + hash: + descr: the block hash (same as provided) + type: bytes32 + confirmations: + descr: The number of confirmations, or -1 if the block is not on the main chain + type: int + height: + descr: The block height or index + type: uint + version: + descr: The block version + type: uint + versionHex: + descr: The block version formatted in hexadecimal + type: hex + merkleroot: + descr: The merkle root ( 32 bytes ) + type: bytes32 + time: + descr: The block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + mediantime: + descr: The median block time in seconds since epoch (Jan 1 1970 GMT) + type: uint + nonce: + descr: The nonce + type: uint + bits: + descr: The bits ( 4 bytes as hex) representing the target + type: bytes4 + difficulty: + descr: The difficulty + type: uint + chainwork: + descr: Expected number of hashes required to produce the current chain (in hex) + type: uint + nTx: + descr: The number of transactions in the block. + type: uint + tx: + descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + array: true + type: bytes32 + previousblockhash: + descr: The hash of the previous block + type: bytes32 + nextblockhash: + descr: The hash of the next block + type: bytes32 + btc: descr: | *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* @@ -140,7 +293,8 @@ btc: type: bytes32 verbosity: descr: 0 or false for the hex-encoded data, 1 or true for a json object - type: uint + type: int + default: 0 in3Params: verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) @@ -148,57 +302,27 @@ btc: preBIP34: descr: defines if the client wants to verify blocks before BIP34 (height < 227836) type: bool - returns: + result: + options: + - params: + verbosity: 0 + name: getblockheaderAsHex + descr: returns a hex representation of the blockheader + result: + optional: true + type: bytes + - params: + verbosity: 1 + name: getblockheader + descr: returns the blockheader + result: + optional: true + type: btcblockheader descr: | the blockheader. - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - verbose `1` or `true`: an object representing the blockheader. - type: - hash: - descr: the block hash (same as provided) - type: bytes32 - confirmations: - descr: The number of confirmations, or -1 if the block is not on the main chain - type: int - height: - descr: The block height or index - type: uint - version: - descr: The block version - type: uint - versionHex: - descr: The block version formatted in hexadecimal - type: hex - merkleroot: - descr: The merkle root ( 32 bytes ) - type: bytes32 - time: - descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint - mediantime: - descr: The median block time in seconds since epoch (Jan 1 1970 GMT) - type: uint - nonce: - descr: The nonce - type: uint - bits: - descr: The bits ( 4 bytes as hex) representing the target - type: bytes4 - difficulty: - descr: The difficulty - type: uint - chainwork: - descr: Expected number of hashes required to produce the current chain (in hex) - type: uint - nTx: - descr: The number of transactions in the block. - type: uint - previousblockhash: - descr: The hash of the previous block - type: bytes32 - nextblockhash: - descr: The hash of the next block - type: bytes32 + type: btcblockheader proof: descr: | @@ -276,7 +400,8 @@ btc: type: bytes32 verbosity: descr: 0 or false for hex-encoded data, 1 or true for a json object, and 2 for json object **with** transaction data - type: uint + type: int + default: 0 in3Params: finality: descr: defines the amount of finality headers @@ -287,60 +412,35 @@ btc: preBIP34: descr: defines if the client wants to verify blocks before BIP34 (height < 227836) type: bool - returns: + result: + options: + - params: + verbosity: 0 + name: getBlockAsHex + descr: returns a hex representation of the block + result: + optional: true + type: bytes + - params: + verbosity: 1 + name: getBlock + descr: returns the block with transactionhashes + result: + optional: true + type: btcblock + - params: + verbosity: 2 + name: getBlockWithTx + descr: returns the block with full transactions + result: + optional: true + type: btcblockWithTx descr: | the block. - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - verbose `1` or `true`: an object representing the blockheader. - type: - hash: - descr: the block hash (same as provided) - type: bytes32 - confirmations: - descr: The number of confirmations, or -1 if the block is not on the main chain - type: int - height: - descr: The block height or index - type: uint - version: - descr: The block version - type: uint - versionHex: - descr: The block version formatted in hexadecimal - type: hex - merkleroot: - descr: The merkle root ( 32 bytes ) - type: bytes32 - time: - descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint - mediantime: - descr: The median block time in seconds since epoch (Jan 1 1970 GMT) - type: uint - nonce: - descr: The nonce - type: uint - bits: - descr: The bits ( 4 bytes as hex) representing the target - type: bytes4 - difficulty: - descr: The difficulty - type: uint - chainwork: - descr: Expected number of hashes required to produce the current chain (in hex) - type: uint - nTx: - descr: The number of transactions in the block. - type: uint - tx: - descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) - type: btctransaction - previousblockhash: - descr: The hash of the previous block - type: bytes32 - nextblockhash: - descr: The hash of the next block - type: bytes32 + type: btcblockWithTx + proof: alias: getblockheader @@ -387,7 +487,7 @@ btc: type: bytes32 verbosity: descr: 0 or false for the hex-encoded data for `txid`, 1 or true for a json object with information about `txid` - type: uint + type: int optional: true default: 1 blockhash: @@ -404,7 +504,22 @@ btc: preBIP34: descr: defines if the client wants to verify blocks before BIP34 (height < 227836) type: bool - returns: + result: + options: + - params: + verbosity: 0 + name: getRawTransactionAsHex + descr: returns a hex representation of the tx + result: + optional: true + type: bytes + - params: + verbosity: 1 + name: getRawTransaction + descr: returns the raw transaction + result: + optional: true + type: btctransaction descr: | - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` - verbose `1` or `false`: an object representing the transaction. @@ -517,7 +632,7 @@ btc: verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string - returns: + result: descr: the current blockheight type: uint proof: @@ -555,6 +670,7 @@ btc: descr: Returns the proof-of-work difficulty as a multiple of the minimum difficulty. params: blocknumber: + type: uint descr: 'Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`)' in3Params: finality: @@ -567,7 +683,8 @@ btc: descr: defines if the client wants to verify blocks before BIP34 (height < 227836) type: bool - returns: + result: + type: uint descr: | - `blocknumber` is a certain number: the difficulty of this block - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) @@ -635,12 +752,17 @@ btc: max_diff: descr: the maximum target difference between 2 verified daps type: uint + default: 5 + optional: true max_dap: descr: the maximum amount of daps between 2 verified daps type: uint + default: 5 + optional: true limit: descr: the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory type: uint + default: 0 optional: true in3Params: finality: @@ -668,7 +790,25 @@ btc: ![](proofTarget.png) - returns: + result: + array: true + type: + dap: + descr: the difficulty adjustement period + type: uint + block: + descr: the first blockheader + type: bytes + final: + descr: the finality header + type: bytes + cbtx: + descr: the coinbase transaction as hex + type: bytes + cbtxMerkleProof: + descr: the coinbasetx merkle proof + type: bytes + descr: A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. proof: descr: | @@ -744,7 +884,7 @@ btc: preBIP34: descr: defines if the client wants to verify blocks before BIP34 (height < 227836) type: bool - returns: + result: descr: the hash of the best block type: bytes32 proof: diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 07bbbee89..10aa5be5a 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -1,4 +1,65 @@ types: + blockdataWithTxHashes: + number: + descr: the block number. `null` when its pending block. + type: uint + hash: + descr: hash of the block. `null` when its pending block. + type: bytes32 + parentHash: + descr: hash of the parent block. + type: bytes32 + nonce: + descr: hash of the generated proof-of-work. `null` when its pending block. + type: uint + sha3Uncles: + descr: SHA3 of the uncles Merkle root in the block. + type: bytes32 + logsBloom: + descr: the bloom filter for the logs of the block. `null` when its pending block. + type: bytes256 + transactionsRoot: + descr: the root of the transaction trie of the block. + type: bytes32 + stateRoot: + descr: the root of the final state trie of the block. + type: bytes32 + receiptsRoot: + descr: the root of the receipts trie of the block. + type: bytes32 + miner: + descr: the address of the beneficiary to whom the mining rewards were given. + type: address + difficulty: + descr: integer of the difficulty for this block. + type: uint + totalDifficulty: + descr: integer of the total difficulty of the chain until this block. + type: uint + extraData: + descr: the "extra data" field of this block. + type: bytes + size: + descr: integer the size of this block in bytes. + type: uint + gasLimit: + descr: the maximum gas allowed in this block. + type: uint + gasUsed: + descr: the total used gas by all transactions in this block. + type: uint + timestamp: + descr: the unix timestamp for when the block was collated. + type: uint + transactions: + descr: Array of transaction hashes + array: true + type: bytes32 + uncles: + descr: Array of uncle hashes. + array: true + type: bytes32 + blockdata: number: descr: the block number. `null` when its pending block. @@ -11,7 +72,7 @@ types: type: bytes32 nonce: descr: hash of the generated proof-of-work. `null` when its pending block. - type: uint64 + type: uint sha3Uncles: descr: SHA3 of the uncles Merkle root in the block. type: bytes32 @@ -52,11 +113,13 @@ types: descr: the unix timestamp for when the block was collated. type: uint transactions: - descr: Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter. - type: transaction[] + descr: Array of transaction objects + array: true + type: transactiondata uncles: descr: Array of uncle hashes. - type: bytes32[] + array: true + type: bytes32 transactiondata: to: @@ -112,8 +175,9 @@ eth: No proof returned, since there is none, but the client should verify the result by comparing it to the current blocks returned from others. With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. - returns: + result: descr: the highest known blocknumber + type: uint example: response: "0xb8a2a5" @@ -246,7 +310,7 @@ eth: fullTx: descr: if true the full transactions are contained in the result. type: bool - returns: + result: descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. type: blockdata @@ -306,7 +370,7 @@ eth: type: bytes32 proof: alias: eth_getUncleCountByBlockNumber - returns: + result: descr: the number of transactions in the block eth_getBlockTransactionCountByNumber: @@ -317,7 +381,7 @@ eth: type: uint proof: alias: eth_getUncleCountByBlockNumber - returns: + result: descr: the number of transactions in the block eth_getUncleCountByBlockHash: @@ -328,7 +392,7 @@ eth: type: bytes32 proof: alias: eth_getUncleCountByBlockNumber - returns: + result: descr: the number of uncles eth_getUncleCountByBlockNumber: @@ -347,7 +411,7 @@ eth: - `transactions`: a array of raw transactions of the block. This is only needed if the number of transactions are requested. - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. - `uncles`: a array of blockheaders of the uncles of the block. This is only needed if the number of uncles are requested. - returns: + result: descr: the number of uncles eth_getTransactionByBlockHashAndIndex: @@ -362,7 +426,7 @@ eth: index: descr: the transactionIndex type: uint - returns: + result: descr: the transactiondata or `null` if it does not exist type: transactiondata proof: @@ -414,7 +478,7 @@ eth: index: descr: the transactionIndex type: uint - returns: + result: descr: the transactiondata or `null` if it does not exist type: transactiondata proof: @@ -463,7 +527,7 @@ eth: txHash: descr: the transactionHash of the transaction. type: bytes32 - returns: + result: descr: the transactiondata or `null` if it does not exist type: transactiondata @@ -656,7 +720,8 @@ eth: optional: true topics: descr: Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. - type: bytes32[] + type: bytes32 + array: true optional: true blockhash: descr: With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. @@ -673,7 +738,7 @@ eth: block: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint - returns: + result: descr: the balance proof: alias: eth_getStorageAt @@ -716,7 +781,7 @@ eth: block: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint - returns: + result: descr: the nonce proof: alias: eth_getStorageAt @@ -760,7 +825,7 @@ eth: block: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint - returns: + result: descr: the code as hex proof: alias: eth_getStorageAt @@ -806,7 +871,7 @@ eth: block: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint - returns: + result: descr: the value of the storage slot. proof: type: @@ -999,7 +1064,7 @@ eth: tx: descr: the transactiondata to send type: transaction - returns: + result: descr: the transactionHash proof: descr: No proof from the nodes are required, because the client can generate the TransactionHash itself. This means to ensure the success of a transaction the receipt needs to be verified. @@ -1010,7 +1075,7 @@ eth: tx: descr: the transactiondata to send type: transaction - returns: + result: descr: the transactionReceipt type: transactionReceipt @@ -1021,7 +1086,7 @@ eth: tx: descr: the raw signed transactiondata to send type: bytes - returns: + result: descr: the transactionhash type: bytes32 diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml index ff7b79e81..6d1a64025 100644 --- a/c/src/verifier/eth1/full/rpc.yml +++ b/c/src/verifier/eth1/full/rpc.yml @@ -10,7 +10,7 @@ eth: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint | string - returns: + result: descr: the amount of gass needed. proof: alias: eth_call @@ -54,7 +54,7 @@ eth: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint | string - returns: + result: descr: the abi-encoded result of the function. example: diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml index 180e0c816..eb8074a2e 100644 --- a/c/src/verifier/eth1/nano/rpc.yml +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -98,7 +98,8 @@ eth: txHash: descr: the transactionHash type: bytes32 - returns: + result: + optional: true descr: the TransactionReceipt or `null` if it does not exist. type: transactionReceipt diff --git a/c/src/verifier/ipfs/rpc.yml b/c/src/verifier/ipfs/rpc.yml index ac11faed7..c90c23a62 100644 --- a/c/src/verifier/ipfs/rpc.yml +++ b/c/src/verifier/ipfs/rpc.yml @@ -9,11 +9,11 @@ ipfs: params: ipfshash: descr: the ipfs multi hash - type: ipfshash + type: string encoding: descr: the encoding used for the response. ( `hex` , `base64` or `utf8`) type: string - returns: + result: descr: the content matching the requested hash encoded in the defined encoding. proof: descr: No proof or verification needed on the server side. All the verification are done in the client by creating the ipfs multihash and comparing to the requested hash. @@ -35,7 +35,7 @@ ipfs: encoding: descr: the encoding used for the request. ( `hex` , `base64` or `utf8`) type: string - returns: + result: descr: the ipfs multi hash example: request: diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift deleted file mode 100644 index ca1160b14..000000000 --- a/swift/Sources/In3/API/Eth.swift +++ /dev/null @@ -1,41 +0,0 @@ -import Foundation - -/// Ethereum API -/// a collection of ethereum-specific functions. -public class Eth { - internal var in3: In3 - - /// initializer with Incubed client - init(_ in3:In3) { - self.in3 = in3 - } - - /// returns the current blockNumber - public func blockNumber() -> Future { - return execAndConvert(in3: in3, method:"eth_blockNumber", convertWith: toUInt64) - } - - /// returns the TransactionReceipt for the given transsaction hash - /// - Paramater hash : the transaction hash - /// the result is an optional value depending on the existence of such a Receipt. - public func getTransactionReceipt(hash:String) -> Future { - return execAndConvertOptional(in3: in3, method:"eth_getTransactionReceipt", params:RPCObject(hash),convertWith: { try EthTransactionReceipt($0,$1) } ) - } - - -} - -/// a TransactionReceipt -public struct EthTransactionReceipt { - - /// the transactionhash - public var hash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc) else { - return nil - } - - hash = try toString(obj["transactionHash"], false)! - } -} From 04a0f0a0f23010a8deb8a2f32df729c0465ddf10 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:07:34 +0200 Subject: [PATCH 102/221] refactore generator --- scripts/build_rpc_docu.js | 124 +++++------------- scripts/generator/swift.js | 260 +++++++++++++++++++++++++++++++++++++ scripts/generator/util.js | 23 ++++ 3 files changed, 313 insertions(+), 94 deletions(-) create mode 100644 scripts/generator/swift.js create mode 100644 scripts/generator/util.js diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 5a7ea627c..d2bc1ef68 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -1,5 +1,16 @@ const yaml = require('../wasm/test/node_modules/yaml') const fs = require('fs') +const swift = require('./generator/swift') +const { + getType, + asArray, + camelCaseLow, + camelCaseUp, + link, + toCmdParam, + short_descr +} = require('./generator/util') + const doc_dir = process.argv[process.argv.length - 1] const main_conf = yaml.parse(fs.readFileSync('../c/src/cmd/in3/in3.yml', 'utf-8')) @@ -8,59 +19,10 @@ const config_doc = [] const main_help = [] const main_aliases = [] const bool_props = [] -const config_bindings = { - swift: { - In3Config: [ - '/// The main Incubed Configuration', - 'public struct In3Config : Codable {', - '', - ' /// create a new Incubed Client based on the Configuration', - ' public func createClient() throws -> In3 {', - ' return try In3(self)', - ' }', - '' - ] - } -} -const api_bindings = { - swift: { - } -} let docs = {}, config = {}, types = {} -const camelCaseUp = s => { - if (!s) return '' - if (s[s.length - 1] == '.') s = s.substr(0, s.length - 1) - s = s.substr(s.lastIndexOf('.') + 1) - return s.substr(0, 1).toUpperCase() + s.substr(1) -} -const camelCaseLow = s => s ? s.substr(0, 1).toLowerCase() + s.substr(1) : '' - -const asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) -const link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' -const getType = val => typeof val === 'object' ? val : (types['' + val] || val) -const toCmdParam = val => (typeof val == 'object' || Array.isArray(val) || ('' + val).indexOf(' ') >= 0) ? "'" + JSON.stringify(val) + "'" : ('' + val) -function createSwiftInitForStruct(s, pad) { - let comments = '\n' + pad + ' /// initialize it memberwise' - let code = '' - let init = '' - let lastDescr = '' - for (let l of s) { - l = l.trim() - if (lastDescr && !l) lastDescr = '' - if (!lastDescr && l.startsWith('/// ')) lastDescr = l.substr(4).split('\n')[0].trim() - if (l.startsWith('public var ')) { - l = l.substr('public var '.length) - const pname = l.substr(0, l.indexOf(':')).trim() - comments += '\n' + pad + ' /// - Parameter ' + pname + ' : ' + lastDescr - code += '\n' + pad + ' self.' + pname + ' = ' + pname - init += (init ? ', ' : '') + l + (l.endsWith('?') ? ' = nil' : '') - lastDescr = '' - } - } - s.push(comments + '\n' + pad + ' public init(' + init + ') {' + code + '\n' + pad + ' }') -} + function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { @@ -78,12 +40,15 @@ function scan(dir) { else if (f.isDirectory()) scan(dir + '/' + f.name) } } + + + function print_object(def, pad, useNum, doc) { let i = 1 for (const prop of Object.keys(def)) { let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' const p = def[prop] - const pt = getType(p.type) + const pt = getType(p.type, types) if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' if (p.optional) s += ' *(optional)*' if (p.descr) s += ' - ' + p.descr @@ -107,31 +72,8 @@ function handle_config(conf, pre, title, descr) { const c = conf[key] // handle bindings - // generate swift - const swift = config_bindings.swift[camelCaseUp(pre || 'In3Config')] - const pad = pre ? ' ' : '' - if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { - //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) - let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) - if (typeof c.type === 'object') { - swiftType = camelCaseUp(key) - config_bindings.swift[swiftType] = [ - ' /// ' + c.descr.replace(/\n/gm, '\n/// '), - ' public struct ' + swiftType + ' : Codable {' - ] - } - else if (swiftType == 'Uint') swiftType = 'UInt64' - else if (swiftType.startsWith('Byte') || swiftType.startsWith('Address')) swiftType = 'String' - if (swiftType.endsWith('[]')) swiftType = '[' + swiftType.substr(0, swiftType.length - 2) + ']' - if (c.array) swiftType = '[' + swiftType + ']' - swift.push('\n' + pad + ' /// ' + ( - c.descr - + (c.default ? ('\n(default: `' + JSON.stringify(c.default) + '`)') : '') - + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') - + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex).trim()).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') - ).replace(/\n/gm, '\n' + pad + ' /// ')) - swift.push(pad + ' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) - } + swift.updateConfig(pre, c, key) + // handle doc if (!pre) { let s = '\n' + (title ? '#' : '') + '## ' + key + '\n\n' + c.descr @@ -174,14 +116,7 @@ function handle_config(conf, pre, title, descr) { } } } -function short_descr(d) { - let zd = (d || '').trim() - if (zd.indexOf('.') >= 0) zd = zd.substr(0, zd.indexOf('.')) - if (zd.indexOf('\n') >= 0) zd = zd.substr(0, zd.indexOf('\n')) - if (zd.indexOf('[') >= 0) zd = zd.substr(0, zd.indexOf('[')) - if (zd.length > 100) zd = zd.substr(0, 100) + '...' - return zd -} + scan('../c/src') docs.in3.in3_config.params.config.type = config rpc_doc.push('# API RPC\n\n') @@ -192,9 +127,14 @@ const zsh_complete = fs.readFileSync('_in3.template', 'utf8') let zsh_cmds = [], zsh_conf = [] for (const s of Object.keys(docs).sort()) { const rpcs = docs[s] + const rdescr = rpcs.descr + rpc_doc.push("## " + s + "\n\n") - if (rpcs.descr) rpc_doc.push(rpcs.descr + '\n') + if (rdescr) rpc_doc.push(rdescr + '\n') delete rpcs.descr + + swift.generateAPI(s, rpcs, rdescr, types) + for (const rpc of Object.keys(rpcs).sort()) { const def = rpcs[rpc] let z = " '" + rpc + ': ' + short_descr((def.descr || (def.alias && rpcs[def.alias].descr) || '')) @@ -213,7 +153,7 @@ for (const s of Object.keys(docs).sort()) { rpc_doc.push("*Parameters:* - \n") if (def.in3Params) { rpc_doc.push('The following in3-configuration will have an impact on the result:\n\n'); - print_object(getType(def.in3Params), '', false, rpc_doc) + print_object(getType(def.in3Params, types), '', false, rpc_doc) rpc_doc.push() } if (def.validation) rpc_doc.push('\n' + def.validation + '\n') @@ -221,7 +161,7 @@ for (const s of Object.keys(docs).sort()) { if (def.returns) { if (def.returns.type) { rpc_doc.push('*Returns:* ' + (typeof def.returns.type === 'string' ? ('`' + def.returns.type + '`') : '`object`') + '\n\n' + def.returns.descr + '\n') - const pt = getType(def.returns.type) + const pt = getType(def.returns.type, types) if (typeof pt === 'object') { rpc_doc.push('\nThe return value contains the following properties :\n') print_object(pt, '', false, rpc_doc) @@ -235,7 +175,7 @@ for (const s of Object.keys(docs).sort()) { if (def.proof) { rpc_doc.push('*Proof:*\n\n' + (def.proof.descr || '') + '\n') - const pt = getType(def.proof.type) + const pt = getType(def.proof.type, types) if (def.proof.alias) rpc_doc.push('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') @@ -276,12 +216,8 @@ for (const s of Object.keys(docs).sort()) { } handle_config(config, '') -Object.keys(config_bindings.swift).forEach(_ => createSwiftInitForStruct(config_bindings.swift[_], _ == 'In3Config' ? '' : ' ')) -fs.writeFileSync('../swift/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( - config_bindings.swift.In3Config.join('\n') + '\n\n' + - Object.keys(config_bindings.swift).filter(_ => _ != 'In3Config').map(type => config_bindings.swift[type].join('\n') + '\n }\n\n').join('') - + '\n}\n' -), { encoding: 'utf8' }) + +swift.generate_config() handle_config(main_conf.config, '', 'cmdline options\n\nThose special options are used in the comandline client to pass additional options.\n') diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js new file mode 100644 index 000000000..480fe3abd --- /dev/null +++ b/scripts/generator/swift.js @@ -0,0 +1,260 @@ +const fs = require('fs') +const yaml = require('../../wasm/test/node_modules/yaml') +const { + getType, + asArray, + camelCaseLow, + camelCaseUp, + link, + toCmdParam +} = require('./util') + +configs = { + In3Config: [ + '/// The main Incubed Configuration', + 'public struct In3Config : Codable {', + '', + ' /// create a new Incubed Client based on the Configuration', + ' public func createClient() throws -> In3 {', + ' return try In3(self)', + ' }', + '' + ] +} +function converterName(swiftType, asFn) { + const type = swiftType.split(/[\[\]_\?\!]+/).join('') + if (type == 'UInt64' || type == 'Double' || type == 'Bool' || type == 'String' || type == 'Int' || type == 'AnyObject') return 'to' + type + if (swiftType.startsWith('[') && asFn) { + if (swiftType.endsWith('?')) + return '{ if let array = try toArray($0,$1) { try array.map({ try ' + type + '($0,true)! }) } }' + else + return '{ try toArray($0,$1)!.map({ try ' + type + '($0,false)! }) }' + } + return asFn ? '{ try ' + type + '($0,$1) }' : type +} +function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api) { + typesGenerated[swiftType] = 'placeholder' + let content = ['/// ' + (descr || swiftType).split('\n').join('\n/// '), + 'public struct ' + swiftType + ' {' + ] + + let toRPC = '\n internal func toRPCDict() -> [String:RPCObject] {\n var obj:[String:RPCObject] = [:]' + let init = ' internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws {' + init += '\n guard let obj = try toObject(rpc, optional) else { return nil }' + + + for (let name of Object.keys(conf)) { + let p = conf[name] + const t = getAPIType(p, typeConfigs, typesGenerated, name, api) + content.push(' /// ' + (p.descr || ('the ' + camelCaseUp(name))).split('\n').join('\n /// ')) + content.push(' public var ' + name + ': ' + t + '\n') + if (p.array) { + if (p.optional) { + init += '\n if let ' + name + ' = try toArray(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ') {' + init += '\n self.' + name + ' = try ' + name + '.map({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' + init += '\n } else {' + init += '\n self.' + name + ' = nil' + init += '\n }' + } + else + init += '\n ' + name + ' = try toArray(obj["' + name + '"])!.map({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' + } + else { + init += '\n ' + name + ' = try ' + converterName(t, false) + '(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ')!' + if (converterName(t, false).startsWith('to')) + toRPC += '\n obj["' + name + '"] = ' + (p.optional ? (name + ' == nil ? RPCObject.none : RPCObject(' + name + '!)') : 'RPCObject(' + name + ')') + } + + } + + typesGenerated[swiftType] = content.join('\n') + '\n' + init + '\n }\n' + toRPC + '\n return obj\n }\n}' +} + +function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { + let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) + let typedef = null + if (typeof c.type === 'object') { + typedef = c.type + swiftType = camelCaseUp(api + camelCaseUp(c.typeName || prefix.startsWith('get') ? prefix.substr(3) : prefix)) + } + else if (typeConfigs[c.type]) { + typedef = typeConfigs[c.type] + swiftType = camelCaseUp((c.type.toLowerCase().startsWith(api.toLowerCase()) ? '' : api) + camelCaseUp(c.type)) + } + else if (swiftType == 'Uint') swiftType = 'UInt64' + else if (swiftType == 'Float') swiftType = 'Double' + else if (swiftType == 'Any') swiftType = 'AnyObject' + else if (swiftType.startsWith('Byte') || swiftType == 'Address' || swiftType == 'Hex') swiftType = 'String' + if (swiftType.endsWith('[]')) { + swiftType = swiftType.substr(0, swiftType.length - 2) + c = { ...c, array: true } + } + if (typedef && !typesGenerated[swiftType]) { + generateStruct(swiftType, typedef, c.descr, typeConfigs, typesGenerated, api); + } + + + if (c.array) swiftType = '[' + swiftType + ']' + if (c.optional) swiftType += '?' + return swiftType +} + +exports.updateConfig = function (pre, c, key) { + // generate swift + const swift = configs[camelCaseUp(pre || 'In3Config')] + const pad = pre ? ' ' : '' + if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { + //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) + let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) + if (typeof c.type === 'object') { + swiftType = camelCaseUp(key) + configs[swiftType] = [ + ' /// ' + c.descr.replace(/\n/gm, '\n/// '), + ' public struct ' + swiftType + ' : Codable {' + ] + } + else if (swiftType == 'Uint') swiftType = 'UInt64' + else if (swiftType.startsWith('Byte') || swiftType.startsWith('Address')) swiftType = 'String' + if (swiftType.endsWith('[]')) swiftType = '[' + swiftType.substr(0, swiftType.length - 2) + ']' + if (c.array) swiftType = '[' + swiftType + ']' + swift.push('\n' + pad + ' /// ' + ( + c.descr + + (c.default ? ('\n(default: `' + JSON.stringify(c.default) + '`)') : '') + + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') + + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex).trim()).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') + ).replace(/\n/gm, '\n' + pad + ' /// ')) + swift.push(pad + ' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) + } +} + + +function createSwiftInitForStruct(s, pad) { + let comments = '\n' + pad + ' /// initialize it memberwise' + let code = '' + let init = '' + let lastDescr = '' + for (let l of s) { + l = l.trim() + if (lastDescr && !l) lastDescr = '' + if (!lastDescr && l.startsWith('/// ')) lastDescr = l.substr(4).split('\n')[0].trim() + if (l.startsWith('public var ')) { + l = l.substr('public var '.length) + const pname = l.substr(0, l.indexOf(':')).trim() + comments += '\n' + pad + ' /// - Parameter ' + pname + ' : ' + lastDescr + code += '\n' + pad + ' self.' + pname + ' = ' + pname + init += (init ? ', ' : '') + l + (l.endsWith('?') ? ' = nil' : '') + lastDescr = '' + } + } + s.push(comments + '\n' + pad + ' public init(' + init + ') {' + code + '\n' + pad + ' }') +} + +exports.generate_config = function () { + Object.keys(configs).forEach(_ => createSwiftInitForStruct(configs[_], _ == 'In3Config' ? '' : ' ')) + fs.writeFileSync('../swift/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( + configs.In3Config.join('\n') + '\n\n' + + Object.keys(configs).filter(_ => _ != 'In3Config').map(type => configs[type].join('\n') + '\n }\n\n').join('') + + '\n}\n' + ), { encoding: 'utf8' }) +} + +function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpcs) { + if (!rpc || rpc.skipApi) return + if (rpc.alias) + return createApiFunction(rpc_name, rpcs[rpc.alias], content, api_name, structs, types, rpcs) + const r = { ...rpc.result, type: (rpc.result || {}).type || 'string' } + if (r.options) { + for (option of r.options) { + let rr = { ...rpc, result: { ...r, ...option.result } } + rr.params = {} + for (let pp of Object.keys(rpc.params)) { + rr.params[pp] = { ...rpc.params[pp] } + if (option.params[pp] != undefined) rr.params[pp].fixed = option.params[pp] + } + delete rr.result.options + rr.apiName = option.name || rr.apiName + rr.descr = option.descr || rr.descr + createApiFunction(rpc_name, rr, content, api_name, structs, types, rpcs) + } + return + } + + if (rpc.descr) content.push(' /// ' + rpc.descr.split('\n').join('\n /// ')) + else content.push(' /// ' + rpc_name) + const fnName = rpc.apiName || camelCaseLow(rpc_name.substr(rpc_name.indexOf('_') + 1)) + let s = ' public func ' + fnName + '(' + let params = '' + if (rpc.params) { + for (let name of Object.keys(rpc.params)) { + let p = rpc.params[name] + let type = getAPIType(p, types, structs, name, camelCaseUp(api_name)) + if (p.fixed === undefined) { + if (!s.endsWith('(')) s += ', ' + content.push(' /// - Parameter ' + name + ' : ' + (p.descr || name).split('\n').join(' /// ')) + s += name + ': ' + type + (p.optional || p.default !== undefined ? ' = ' + (p.default !== undefined ? JSON.stringify(p.default) : 'nil') : '') + } + params += (params ? '' : 'params:') + ( + p.fixed === undefined + ? (p.optional + ? name + ' == nil ? RPCObject.none : RPCObject(' + name + '!),' + : ' RPCObject(' + (converterName(type, false).startsWith('to') ? name : (name + '.toRPCDict()')) + '),') + : (' RPCObject(' + JSON.stringify(p.fixed) + '), ') + ) + + } + } + const returnType = getAPIType(r, types, structs, fnName, camelCaseUp(api_name)) + if (rpc.sync) { + s += ') throws -> ' + returnType.replace("AnyObject", "RPCObject") + ' {' + s += '\n return try execLocalAndConvert(in3: in3, method: "' + rpc_name + '",' + params + if (returnType == '[AnyObject]') + s += ' convertWith: { try toArray($0,$1)! } )' + else + s += ' convertWith: ' + converterName(returnType, true) + ' )' + s += '\n }\n' + } + else { + s += ') -> Future<' + returnType + '> {' + s += '\n return execAndConvert' + (r.optional ? 'Optional' : '') + '(in3: in3, method: "' + rpc_name + '",' + params + s += ' convertWith: ' + converterName(returnType, true) + ' )' + s += '\n }\n' + } + if (r.descr) content.push(' /// - Returns: ' + rpc.result.descr.split('\n').join(' /// ')) + content.push(s) +} + +exports.generateAPI = function (api_name, rpcs, descr, types) { + const structs = {} + const apiName = camelCaseUp(api_name) + 'API' + const content = [ + '/// this is generated file don\'t edit it manually!', + '', + 'import Foundation', + '', + '/// ' + descr.split('\n').join('\n/// '), + 'public class ' + apiName + ' {', + ' internal var in3: In3', + '', + ' /// initialiazes the ' + camelCaseUp(api_name) + ' API', + ' /// - Parameter in3 : the incubed Client', + ' init(_ in3: In3) {', + ' self.in3 = in3', + ' }', + '' + ] + Object.keys(rpcs).forEach(rpc_name => createApiFunction(rpc_name, rpcs[rpc_name], content, api_name, structs, types, rpcs)) + + fs.writeFileSync('../swift/Sources/In3/API/' + apiName + '.swift', ( + content.join('\n') + '\n\n}\n' + + Object.values(structs).join('\n\n') + ), 'utf8') +} + + + +function generate_swift_api(all) { + Object.keys(all).forEach(api_key => { + const api = all[api_key] + + }) +} diff --git a/scripts/generator/util.js b/scripts/generator/util.js new file mode 100644 index 000000000..783c408cb --- /dev/null +++ b/scripts/generator/util.js @@ -0,0 +1,23 @@ +const camelCase = n => n.split('_').map(_ => _.substr(0, 1).toUpperCase() + _.substr(1)).join('') + +exports.camelCase = camelCase +exports.camelCaseUp = s => { + if (!s) return '' + if (s[s.length - 1] == '.') s = s.substr(0, s.length - 1) + s = s.substr(s.lastIndexOf('.') + 1) + return s.substr(0, 1).toUpperCase() + camelCase(s).substr(1) +} +exports.camelCaseLow = s => s ? s.substr(0, 1).toLowerCase() + camelCase(s).substr(1) : '' + +exports.asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) +exports.link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' +exports.getType = (val, types) => typeof val === 'object' ? val : (types['' + val] || val) +exports.toCmdParam = val => (typeof val == 'object' || Array.isArray(val) || ('' + val).indexOf(' ') >= 0) ? "'" + JSON.stringify(val) + "'" : ('' + val) +exports.short_descr = function (d) { + let zd = (d || '').trim() + if (zd.indexOf('.') >= 0) zd = zd.substr(0, zd.indexOf('.')) + if (zd.indexOf('\n') >= 0) zd = zd.substr(0, zd.indexOf('\n')) + if (zd.indexOf('[') >= 0) zd = zd.substr(0, zd.indexOf('[')) + if (zd.length > 100) zd = zd.substr(0, 100) + '...' + return zd +} \ No newline at end of file From e94b55d9aeba325284aec7b01702b0d45ba0aa09 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:07:55 +0200 Subject: [PATCH 103/221] generate API --- swift/Sources/In3/API/BtcAPI.swift | 628 ++++++++++++++++++++++ swift/Sources/In3/API/EthAPI.swift | 746 ++++++++++++++++++++++++++ swift/Sources/In3/API/In3API.swift | 483 +++++++++++++++++ swift/Sources/In3/API/IpfsAPI.swift | 38 ++ swift/Sources/In3/API/ZksyncAPI.swift | 547 +++++++++++++++++++ swift/Sources/In3/In3.swift | 8 +- swift/Sources/In3/Utils/Convert.swift | 62 +++ swift/Sources/In3/Utils/JsonRpc.swift | 36 ++ swift/Tests/In3Tests/In3Tests.swift | 5 +- swift/docs/1_intro.md | 5 - 10 files changed, 2550 insertions(+), 8 deletions(-) create mode 100644 swift/Sources/In3/API/BtcAPI.swift create mode 100644 swift/Sources/In3/API/EthAPI.swift create mode 100644 swift/Sources/In3/API/In3API.swift create mode 100644 swift/Sources/In3/API/IpfsAPI.swift create mode 100644 swift/Sources/In3/API/ZksyncAPI.swift diff --git a/swift/Sources/In3/API/BtcAPI.swift b/swift/Sources/In3/API/BtcAPI.swift new file mode 100644 index 000000000..598bf77f6 --- /dev/null +++ b/swift/Sources/In3/API/BtcAPI.swift @@ -0,0 +1,628 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* +/// +/// For bitcoin incubed follows the specification as defined in [https://bitcoincore.org/en/doc/0.18.0/](https://bitcoincore.org/en/doc/0.18.0/). +/// Internally the in3-server will add proofs as part of the responses. The proof data differs between the methods. You will read which proof data will be provided and how the data can be used to prove the result for each method. +/// +/// Proofs will add a special `in3`-section to the response containing a `proof`- object. This object will contain parts or all of the following properties: +/// +/// * **block** +/// * **final** +/// * **txIndex** +/// * **merkleProof** +/// * **cbtx** +/// * **cbtxMerkleProof** +/// +public class BtcAPI { + internal var in3: In3 + + /// initialiazes the Btc API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// returns a hex representation of the blockheader + /// - Parameter hash : The block hash + /// - Returns: the blockheader. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + public func getblockheaderAsHex(hash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(0), convertWith: toString ) + } + + /// returns the blockheader + /// - Parameter hash : The block hash + /// - Returns: the blockheader. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + public func getblockheader(hash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblockheader($0,$1) } ) + } + + /// returns a hex representation of the block + /// - Parameter hash : The block hash + /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + public func getBlockAsHex(hash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(0), convertWith: toString ) + } + + /// returns the block with transactionhashes + /// - Parameter hash : The block hash + /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + public func getBlock(hash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblock($0,$1) } ) + } + + /// returns the block with full transactions + /// - Parameter hash : The block hash + /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + public func getBlockWithTx(hash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(2), convertWith: { try BtcblockWithTx($0,$1) } ) + } + + /// returns a hex representation of the tx + /// - Parameter txid : The transaction id + /// - Parameter blockhash : The block in which to look for the transaction + /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` /// - verbose `1` or `false`: an object representing the transaction. /// + public func getRawTransactionAsHex(txid: String, blockhash: String? = nil) -> Future { + return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(0), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: toString ) + } + + /// returns the raw transaction + /// - Parameter txid : The transaction id + /// - Parameter blockhash : The block in which to look for the transaction + /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` /// - verbose `1` or `false`: an object representing the transaction. /// + public func getRawTransaction(txid: String, blockhash: String? = nil) -> Future { + return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(1), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: { try Btctransaction($0,$1) } ) + } + + /// Returns the number of blocks in the longest blockchain. + /// - Returns: the current blockheight + public func getblockcount() -> Future { + return execAndConvert(in3: in3, method: "getblockcount", convertWith: toUInt64 ) + } + + /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. + /// - Parameter blocknumber : Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`) + /// - Returns: - `blocknumber` is a certain number: the difficulty of this block /// - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) /// + public func getdifficulty(blocknumber: UInt64) -> Future { + return execAndConvert(in3: in3, method: "getdifficulty",params: RPCObject(blocknumber), convertWith: toUInt64 ) + } + + /// Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. + /// - Parameter target_dap : the number of the difficulty adjustment period (dap) we are looking for + /// - Parameter verified_dap : the number of the closest already verified dap + /// - Parameter max_diff : the maximum target difference between 2 verified daps + /// - Parameter max_dap : the maximum amount of daps between 2 verified daps + /// - Parameter limit : the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory + /// - Returns: A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. + public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: UInt64? = 5, max_dap: UInt64? = 5, limit: UInt64? = 0) -> Future<[BtcProofTarget]> { + return execAndConvert(in3: in3, method: "btc_proofTarget",params: RPCObject(target_dap), RPCObject(verified_dap),max_diff == nil ? RPCObject.none : RPCObject(max_diff!),max_dap == nil ? RPCObject.none : RPCObject(max_dap!),limit == nil ? RPCObject.none : RPCObject(limit!), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) + } + + /// Returns the hash of the best (tip) block in the longest blockchain. + /// - Returns: the hash of the best block + public func getbestblockhash() -> Future { + return execAndConvert(in3: in3, method: "getbestblockhash", convertWith: toString ) + } + + +} +/// the blockheader. +/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader +/// - verbose `1` or `true`: an object representing the blockheader. +/// +public struct Btcblockheader { + /// the block hash (same as provided) + public var hash: String + + /// The number of confirmations, or -1 if the block is not on the main chain + public var confirmations: Int + + /// The block height or index + public var height: UInt64 + + /// The block version + public var version: UInt64 + + /// The block version formatted in hexadecimal + public var versionHex: String + + /// The merkle root ( 32 bytes ) + public var merkleroot: String + + /// The block time in seconds since epoch (Jan 1 1970 GMT) + public var time: UInt64 + + /// The median block time in seconds since epoch (Jan 1 1970 GMT) + public var mediantime: UInt64 + + /// The nonce + public var nonce: UInt64 + + /// The bits ( 4 bytes as hex) representing the target + public var bits: String + + /// The difficulty + public var difficulty: UInt64 + + /// Expected number of hashes required to produce the current chain (in hex) + public var chainwork: UInt64 + + /// The number of transactions in the block. + public var nTx: UInt64 + + /// The hash of the previous block + public var previousblockhash: String + + /// The hash of the next block + public var nextblockhash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + hash = try toString(obj["hash"],false)! + confirmations = try toInt(obj["confirmations"],false)! + height = try toUInt64(obj["height"],false)! + version = try toUInt64(obj["version"],false)! + versionHex = try toString(obj["versionHex"],false)! + merkleroot = try toString(obj["merkleroot"],false)! + time = try toUInt64(obj["time"],false)! + mediantime = try toUInt64(obj["mediantime"],false)! + nonce = try toUInt64(obj["nonce"],false)! + bits = try toString(obj["bits"],false)! + difficulty = try toUInt64(obj["difficulty"],false)! + chainwork = try toUInt64(obj["chainwork"],false)! + nTx = try toUInt64(obj["nTx"],false)! + previousblockhash = try toString(obj["previousblockhash"],false)! + nextblockhash = try toString(obj["nextblockhash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["hash"] = RPCObject(hash) + obj["confirmations"] = RPCObject(confirmations) + obj["height"] = RPCObject(height) + obj["version"] = RPCObject(version) + obj["versionHex"] = RPCObject(versionHex) + obj["merkleroot"] = RPCObject(merkleroot) + obj["time"] = RPCObject(time) + obj["mediantime"] = RPCObject(mediantime) + obj["nonce"] = RPCObject(nonce) + obj["bits"] = RPCObject(bits) + obj["difficulty"] = RPCObject(difficulty) + obj["chainwork"] = RPCObject(chainwork) + obj["nTx"] = RPCObject(nTx) + obj["previousblockhash"] = RPCObject(previousblockhash) + obj["nextblockhash"] = RPCObject(nextblockhash) + return obj + } +} + +/// the block. +/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader +/// - verbose `1` or `true`: an object representing the blockheader. +/// +public struct Btcblock { + /// the block hash (same as provided) + public var hash: String + + /// The number of confirmations, or -1 if the block is not on the main chain + public var confirmations: Int + + /// The block height or index + public var height: UInt64 + + /// The block version + public var version: UInt64 + + /// The block version formatted in hexadecimal + public var versionHex: String + + /// The merkle root ( 32 bytes ) + public var merkleroot: String + + /// The block time in seconds since epoch (Jan 1 1970 GMT) + public var time: UInt64 + + /// The median block time in seconds since epoch (Jan 1 1970 GMT) + public var mediantime: UInt64 + + /// The nonce + public var nonce: UInt64 + + /// The bits ( 4 bytes as hex) representing the target + public var bits: String + + /// The difficulty + public var difficulty: UInt64 + + /// Expected number of hashes required to produce the current chain (in hex) + public var chainwork: UInt64 + + /// The number of transactions in the block. + public var nTx: UInt64 + + /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + public var tx: [String] + + /// The hash of the previous block + public var previousblockhash: String + + /// The hash of the next block + public var nextblockhash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + hash = try toString(obj["hash"],false)! + confirmations = try toInt(obj["confirmations"],false)! + height = try toUInt64(obj["height"],false)! + version = try toUInt64(obj["version"],false)! + versionHex = try toString(obj["versionHex"],false)! + merkleroot = try toString(obj["merkleroot"],false)! + time = try toUInt64(obj["time"],false)! + mediantime = try toUInt64(obj["mediantime"],false)! + nonce = try toUInt64(obj["nonce"],false)! + bits = try toString(obj["bits"],false)! + difficulty = try toUInt64(obj["difficulty"],false)! + chainwork = try toUInt64(obj["chainwork"],false)! + nTx = try toUInt64(obj["nTx"],false)! + tx = try toArray(obj["tx"])!.map({ try toString($0,false)! }) + previousblockhash = try toString(obj["previousblockhash"],false)! + nextblockhash = try toString(obj["nextblockhash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["hash"] = RPCObject(hash) + obj["confirmations"] = RPCObject(confirmations) + obj["height"] = RPCObject(height) + obj["version"] = RPCObject(version) + obj["versionHex"] = RPCObject(versionHex) + obj["merkleroot"] = RPCObject(merkleroot) + obj["time"] = RPCObject(time) + obj["mediantime"] = RPCObject(mediantime) + obj["nonce"] = RPCObject(nonce) + obj["bits"] = RPCObject(bits) + obj["difficulty"] = RPCObject(difficulty) + obj["chainwork"] = RPCObject(chainwork) + obj["nTx"] = RPCObject(nTx) + obj["previousblockhash"] = RPCObject(previousblockhash) + obj["nextblockhash"] = RPCObject(nextblockhash) + return obj + } +} + +/// the block. +/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader +/// - verbose `1` or `true`: an object representing the blockheader. +/// +public struct BtcblockWithTx { + /// the block hash (same as provided) + public var hash: String + + /// The number of confirmations, or -1 if the block is not on the main chain + public var confirmations: Int + + /// The block height or index + public var height: UInt64 + + /// The block version + public var version: UInt64 + + /// The block version formatted in hexadecimal + public var versionHex: String + + /// The merkle root ( 32 bytes ) + public var merkleroot: String + + /// The block time in seconds since epoch (Jan 1 1970 GMT) + public var time: UInt64 + + /// The median block time in seconds since epoch (Jan 1 1970 GMT) + public var mediantime: UInt64 + + /// The nonce + public var nonce: UInt64 + + /// The bits ( 4 bytes as hex) representing the target + public var bits: String + + /// The difficulty + public var difficulty: UInt64 + + /// Expected number of hashes required to produce the current chain (in hex) + public var chainwork: UInt64 + + /// The number of transactions in the block. + public var nTx: UInt64 + + /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + public var tx: [Btctransaction] + + /// The hash of the previous block + public var previousblockhash: String + + /// The hash of the next block + public var nextblockhash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + hash = try toString(obj["hash"],false)! + confirmations = try toInt(obj["confirmations"],false)! + height = try toUInt64(obj["height"],false)! + version = try toUInt64(obj["version"],false)! + versionHex = try toString(obj["versionHex"],false)! + merkleroot = try toString(obj["merkleroot"],false)! + time = try toUInt64(obj["time"],false)! + mediantime = try toUInt64(obj["mediantime"],false)! + nonce = try toUInt64(obj["nonce"],false)! + bits = try toString(obj["bits"],false)! + difficulty = try toUInt64(obj["difficulty"],false)! + chainwork = try toUInt64(obj["chainwork"],false)! + nTx = try toUInt64(obj["nTx"],false)! + tx = try toArray(obj["tx"])!.map({ try Btctransaction($0,false)! }) + previousblockhash = try toString(obj["previousblockhash"],false)! + nextblockhash = try toString(obj["nextblockhash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["hash"] = RPCObject(hash) + obj["confirmations"] = RPCObject(confirmations) + obj["height"] = RPCObject(height) + obj["version"] = RPCObject(version) + obj["versionHex"] = RPCObject(versionHex) + obj["merkleroot"] = RPCObject(merkleroot) + obj["time"] = RPCObject(time) + obj["mediantime"] = RPCObject(mediantime) + obj["nonce"] = RPCObject(nonce) + obj["bits"] = RPCObject(bits) + obj["difficulty"] = RPCObject(difficulty) + obj["chainwork"] = RPCObject(chainwork) + obj["nTx"] = RPCObject(nTx) + obj["previousblockhash"] = RPCObject(previousblockhash) + obj["nextblockhash"] = RPCObject(nextblockhash) + return obj + } +} + +/// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) +public struct Btctransaction { + /// txid + public var txid: String + + /// Whether specified block is in the active chain or not (only present with explicit "blockhash" argument) + public var in_active_chain: Bool + + /// The serialized, hex-encoded data for `txid` + public var hex: String + + /// The transaction hash (differs from txid for witness transactions) + public var hash: String + + /// The serialized transaction size + public var size: UInt64 + + /// The virtual transaction size (differs from size for witness transactions) + public var vsize: UInt64 + + /// The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) + public var weight: UInt64 + + /// The version + public var version: UInt64 + + /// The lock time + public var locktime: UInt64 + + /// array of json objects of incoming txs to be used + public var vin: [BtcVin] + + /// array of json objects describing the tx outputs + public var vout: [BtcVout] + + /// the block hash + public var blockhash: String + + /// The confirmations + public var confirmations: Int + + /// The block time in seconds since epoch (Jan 1 1970 GMT) + public var blocktime: UInt64 + + /// Same as "blocktime" + public var time: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + txid = try toString(obj["txid"],false)! + in_active_chain = try toBool(obj["in_active_chain"],false)! + hex = try toString(obj["hex"],false)! + hash = try toString(obj["hash"],false)! + size = try toUInt64(obj["size"],false)! + vsize = try toUInt64(obj["vsize"],false)! + weight = try toUInt64(obj["weight"],false)! + version = try toUInt64(obj["version"],false)! + locktime = try toUInt64(obj["locktime"],false)! + vin = try toArray(obj["vin"])!.map({ try BtcVin($0,false)! }) + vout = try toArray(obj["vout"])!.map({ try BtcVout($0,false)! }) + blockhash = try toString(obj["blockhash"],false)! + confirmations = try toInt(obj["confirmations"],false)! + blocktime = try toUInt64(obj["blocktime"],false)! + time = try toUInt64(obj["time"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["txid"] = RPCObject(txid) + obj["in_active_chain"] = RPCObject(in_active_chain) + obj["hex"] = RPCObject(hex) + obj["hash"] = RPCObject(hash) + obj["size"] = RPCObject(size) + obj["vsize"] = RPCObject(vsize) + obj["weight"] = RPCObject(weight) + obj["version"] = RPCObject(version) + obj["locktime"] = RPCObject(locktime) + obj["blockhash"] = RPCObject(blockhash) + obj["confirmations"] = RPCObject(confirmations) + obj["blocktime"] = RPCObject(blocktime) + obj["time"] = RPCObject(time) + return obj + } +} + +/// array of json objects of incoming txs to be used +public struct BtcVin { + /// the transaction id + public var txid: String + + /// the index of the transaction out to be used + public var vout: UInt64 + + /// the script + public var scriptSig: BtcScriptSig + + /// The script sequence number + public var sequence: UInt64 + + /// hex-encoded witness data (if any) + public var txinwitness: [String] + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + txid = try toString(obj["txid"],false)! + vout = try toUInt64(obj["vout"],false)! + scriptSig = try BtcScriptSig(obj["scriptSig"],false)! + sequence = try toUInt64(obj["sequence"],false)! + txinwitness = try toArray(obj["txinwitness"])!.map({ try toString($0,false)! }) + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["txid"] = RPCObject(txid) + obj["vout"] = RPCObject(vout) + obj["sequence"] = RPCObject(sequence) + return obj + } +} + +/// the script +public struct BtcScriptSig { + /// the asm-codes + public var asm: String + + /// hex representation + public var hex: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + asm = try toString(obj["asm"],false)! + hex = try toString(obj["hex"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["asm"] = RPCObject(asm) + obj["hex"] = RPCObject(hex) + return obj + } +} + +/// array of json objects describing the tx outputs +public struct BtcVout { + /// The Value in BTC + public var value: UInt64 + + /// the index + public var n: UInt64 + + /// the script pubkey + public var scriptPubKey: BtcScriptPubKey + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + value = try toUInt64(obj["value"],false)! + n = try toUInt64(obj["n"],false)! + scriptPubKey = try BtcScriptPubKey(obj["scriptPubKey"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["value"] = RPCObject(value) + obj["n"] = RPCObject(n) + return obj + } +} + +/// the script pubkey +public struct BtcScriptPubKey { + /// asm + public var asm: String + + /// hex representation of the script + public var hex: String + + /// the required signatures + public var reqSigs: UInt64 + + /// The type, eg 'pubkeyhash' + public var type: String + + /// Array of address(each representing a bitcoin adress) + public var addresses: [String] + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + asm = try toString(obj["asm"],false)! + hex = try toString(obj["hex"],false)! + reqSigs = try toUInt64(obj["reqSigs"],false)! + type = try toString(obj["type"],false)! + addresses = try toArray(obj["addresses"])!.map({ try toString($0,false)! }) + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["asm"] = RPCObject(asm) + obj["hex"] = RPCObject(hex) + obj["reqSigs"] = RPCObject(reqSigs) + obj["type"] = RPCObject(type) + return obj + } +} + +/// A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. +public struct BtcProofTarget { + /// the difficulty adjustement period + public var dap: UInt64 + + /// the first blockheader + public var block: String + + /// the finality header + public var final: String + + /// the coinbase transaction as hex + public var cbtx: String + + /// the coinbasetx merkle proof + public var cbtxMerkleProof: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + dap = try toUInt64(obj["dap"],false)! + block = try toString(obj["block"],false)! + final = try toString(obj["final"],false)! + cbtx = try toString(obj["cbtx"],false)! + cbtxMerkleProof = try toString(obj["cbtxMerkleProof"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["dap"] = RPCObject(dap) + obj["block"] = RPCObject(block) + obj["final"] = RPCObject(final) + obj["cbtx"] = RPCObject(cbtx) + obj["cbtxMerkleProof"] = RPCObject(cbtxMerkleProof) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/API/EthAPI.swift b/swift/Sources/In3/API/EthAPI.swift new file mode 100644 index 000000000..b0604e4f2 --- /dev/null +++ b/swift/Sources/In3/API/EthAPI.swift @@ -0,0 +1,746 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// Standard JSON-RPC calls as described in https://eth.wiki/json-rpc/API. +/// +/// Whenever a request is made for a response with `verification`: `proof`, the node must provide the proof needed to validate the response result. The proof itself depends on the chain. +/// +/// For ethereum, all proofs are based on the correct block hash. That's why verification differentiates between [Verifying the blockhash](poa.html) (which depends on the user consensus) the actual result data. +/// +/// There is another reason why the BlockHash is so important. This is the only value you are able to access from within a SmartContract, because the evm supports a OpCode (`BLOCKHASH`), which allows you to read the last 256 blockhashes, which gives us the chance to verify even the blockhash onchain. +/// +/// Depending on the method, different proofs are needed, which are described in this document. +/// +/// Proofs will add a special in3-section to the response containing a `proof`- object. Each `in3`-section of the response containing proofs has a property with a proof-object with the following properties: +/// +/// * **type** `string` (required) - The type of the proof. +/// Must be one of the these values : `'transactionProof`', `'receiptProof`', `'blockProof`', `'accountProof`', `'callProof`', `'logProof`' +/// * **block** `string` - The serialized blockheader as hex, required in most proofs. +/// * **finalityBlocks** `array` - The serialized following blockheaders as hex, required in case of finality asked (only relevant for PoA-chains). The server must deliver enough blockheaders to cover more then 50% of the validators. In order to verify them, they must be linkable (with the parentHash). +/// * **transactions** `array` - The list of raw transactions of the block if needed to create a merkle trie for the transactions. +/// * **uncles** `array` - The list of uncle-headers of the block. This will only be set if full verification is required in order to create a merkle tree for the uncles and so prove the uncle_hash. +/// * **merkleProof** `string[]` - The serialized merkle-nodes beginning with the root-node (depending on the content to prove). +/// * **merkleProofPrev** `string[]` - The serialized merkle-nodes beginning with the root-node of the previous entry (only for full proof of receipts). +/// * **txProof** `string[]` - The serialized merkle-nodes beginning with the root-node in order to proof the transactionIndex (only needed for transaction receipts). +/// * **logProof** [LogProof](#logproof) - The Log Proof in case of a `eth_getLogs`-request. +/// * **accounts** `object` - A map of addresses and their AccountProof. +/// * **txIndex** `integer` - The transactionIndex within the block (for transaactions and receipts). +/// * **signatures** `Signature[]` - Requested signatures. +/// +public class EthAPI { + internal var in3: In3 + + /// initialiazes the Eth API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. + /// - Returns: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. + public func clientVersion() -> Future { + return execAndConvert(in3: in3, method: "web3_clientVersion", convertWith: toString ) + } + + /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. + /// + /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + public func keccak(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "keccak",params: RPCObject(data), convertWith: toString ) + } + + /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. + /// + /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + public func sha3(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "web3_sha3",params: RPCObject(data), convertWith: toString ) + } + + /// Returns sha-256 of the given data. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + public func sha256(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "sha256",params: RPCObject(data), convertWith: toString ) + } + + /// the Network Version (currently 1) + /// - Returns: the Version number + public func version() throws -> String { + return try execLocalAndConvert(in3: in3, method: "net_version", convertWith: toString ) + } + + /// Generates 32 random bytes. + /// If /dev/urandom is available it will be used and should generate a secure random number. + /// If not the number should not be considered sceure or used in production. + /// + /// - Parameter seed : the seed. If given the result will be deterministic. + /// - Returns: the 32byte random data + public func createKey(seed: String? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_createKey",params:seed == nil ? RPCObject.none : RPCObject(seed!), convertWith: toString ) + } + + /// The sign method calculates an Ethereum specific signature with: + /// + /// ```js + /// sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). + /// ``` + /// + /// By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + /// + /// For the address to sign a signer must be registered. + /// + /// - Parameter account : the account to sign with + /// - Parameter message : the message to sign + /// - Returns: the signature (65 bytes) for the given message. + public func sign(account: String, message: String) -> Future { + return execAndConvert(in3: in3, method: "eth_sign",params: RPCObject(account), RPCObject(message), convertWith: toString ) + } + + /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. + /// - Parameter tx : transaction to sign + /// - Returns: the raw signed transaction + public func signTransaction(tx: EthTransaction) -> Future { + return execAndConvert(in3: in3, method: "eth_signTransaction",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + } + + /// returns the number of the most recent block. + /// + /// See [eth_blockNumber](https://eth.wiki/json-rpc/API#eth_blockNumber) for spec. + /// + /// No proof returned, since there is none, but the client should verify the result by comparing it to the current blocks returned from others. + /// With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. + /// + /// - Returns: the highest known blocknumber + public func blockNumber() -> Future { + return execAndConvert(in3: in3, method: "eth_blockNumber", convertWith: toUInt64 ) + } + + /// returns information about a block by block number. + /// + /// See [eth_getBlockByNumber](https://eth.wiki/json-rpc/API#eth_getBlockByNumber) for spec. + /// + /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter fullTx : if true the full transactions are contained in the result. + /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. + public func getBlockByNumber(blockNumber: UInt64, fullTx: Bool) -> Future { + return execAndConvert(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(fullTx), convertWith: { try EthBlockdata($0,$1) } ) + } + + /// Returns information about a block by hash. + /// + /// See [eth_getBlockByHash](https://eth.wiki/json-rpc/API#eth_getBlockByHash) for spec. + /// + /// - Parameter blockHash : the blockHash of the block + /// - Parameter fullTx : if true the full transactions are contained in the result. + /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. + public func getBlockByHash(blockHash: String, fullTx: Bool) -> Future { + return execAndConvert(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(fullTx), convertWith: { try EthBlockdata($0,$1) } ) + } + + /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByHash). + /// - Parameter blockHash : the blockHash of the block + /// - Returns: the number of transactions in the block + public func getBlockTransactionCountByHash(blockHash: String) -> Future { + return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByHash",params: RPCObject(blockHash), convertWith: toString ) + } + + /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByNumber). + /// - Parameter blockNumber : the blockNumber of the block + /// - Returns: the number of transactions in the block + public func getBlockTransactionCountByNumber(blockNumber: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber",params: RPCObject(blockNumber), convertWith: toString ) + } + + /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). + /// - Parameter blockHash : the blockHash of the block + /// - Returns: the number of uncles + public func getUncleCountByBlockHash(blockHash: String) -> Future { + return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockHash",params: RPCObject(blockHash), convertWith: toString ) + } + + /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockNumber). + /// - Parameter blockNumber : the blockNumber of the block + /// - Returns: the number of uncles + public func getUncleCountByBlockNumber(blockNumber: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber",params: RPCObject(blockNumber), convertWith: toString ) + } + + /// returns the transaction data. + /// + /// See JSON-RPC-Spec for [eth_getTransactionByBlockHashAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockHashAndIndex) for more details. + /// + /// - Parameter blockHash : the blockhash containing the transaction. + /// - Parameter index : the transactionIndex + /// - Returns: the transactiondata or `null` if it does not exist + public func getTransactionByBlockHashAndIndex(blockHash: String, index: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex",params: RPCObject(blockHash), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) + } + + /// returns the transaction data. + /// + /// See JSON-RPC-Spec for [eth_getTransactionByBlockNumberAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockNumberAndIndex) for more details. + /// + /// - Parameter blockNumber : the block number containing the transaction. + /// - Parameter index : the transactionIndex + /// - Returns: the transactiondata or `null` if it does not exist + public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex",params: RPCObject(blockNumber), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) + } + + /// returns the transaction data. + /// + /// See JSON-RPC-Spec for [eth_getTransactionByHash](https://eth.wiki/json-rpc/API#eth_getTransactionByHash) for more details. + /// + /// - Parameter txHash : the transactionHash of the transaction. + /// - Returns: the transactiondata or `null` if it does not exist + public func getTransactionByHash(txHash: String) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionByHash",params: RPCObject(txHash), convertWith: { try EthTransactiondata($0,$1) } ) + } + + /// searches for events matching the given criteria. See [eth_getLogs](https://eth.wiki/json-rpc/API#eth_getLogs) for the spec. + /// - Parameter filter : The filter criteria for the events. + public func getLogs(filter: EthFilter) -> Future { + return execAndConvert(in3: in3, method: "eth_getLogs",params: RPCObject(filter.toRPCDict()), convertWith: toString ) + } + + /// gets the balance of an account for a given block + /// - Parameter account : address of the account + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the balance + public func getBalance(account: String, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getBalance",params: RPCObject(account), RPCObject(block), convertWith: toString ) + } + + /// gets the nonce or number of transaction sent from this account at a given block + /// - Parameter account : address of the account + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the nonce + public func getTransactionCount(account: String, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionCount",params: RPCObject(account), RPCObject(block), convertWith: toString ) + } + + /// gets the code of a given contract + /// - Parameter account : address of the account + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the code as hex + public func getCode(account: String, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getCode",params: RPCObject(account), RPCObject(block), convertWith: toString ) + } + + /// gets the storage value of a given key + /// - Parameter account : address of the account + /// - Parameter key : key to look for + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the value of the storage slot. + public func getStorageAt(account: String, key: String, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_getStorageAt",params: RPCObject(account), RPCObject(key), RPCObject(block), convertWith: toString ) + } + + /// signs and sends a Transaction + /// - Parameter tx : the transactiondata to send + /// - Returns: the transactionHash + public func sendTransaction(tx: EthTransaction) -> Future { + return execAndConvert(in3: in3, method: "eth_sendTransaction",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + } + + /// signs and sends a Transaction, but then waits until the transaction receipt can be verified. Depending on the finality of the nodes, this may take a while, since only final blocks will be signed by the nodes. + /// - Parameter tx : the transactiondata to send + /// - Returns: the transactionReceipt + public func sendTransactionAndWait(tx: EthTransaction) -> Future { + return execAndConvert(in3: in3, method: "eth_sendTransactionAndWait",params: RPCObject(tx.toRPCDict()), convertWith: { try EthTransactionReceipt($0,$1) } ) + } + + /// sends or broadcasts a prviously signed raw transaction. See [eth_sendRawTransaction](https://eth.wiki/json-rpc/API#eth_sendRawTransaction) + /// - Parameter tx : the raw signed transactiondata to send + /// - Returns: the transactionhash + public func sendRawTransaction(tx: String) -> Future { + return execAndConvert(in3: in3, method: "eth_sendRawTransaction",params: RPCObject(tx), convertWith: toString ) + } + + /// calculates the gas needed to execute a transaction. for spec see [eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimateGas) + /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the amount of gass needed. + public func estimateGas(tx: EthTransaction, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_estimateGas",params: RPCObject(tx.toRPCDict()), RPCObject(block), convertWith: toString ) + } + + /// calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) + /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the abi-encoded result of the function. + public func call(tx: EthTx, block: UInt64) -> Future { + return execAndConvert(in3: in3, method: "eth_call",params: RPCObject(tx.toRPCDict()), RPCObject(block), convertWith: toString ) + } + + /// The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). + /// - Parameter txHash : the transactionHash + /// - Returns: the TransactionReceipt or `null` if it does not exist. + public func getTransactionReceipt(txHash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getTransactionReceipt",params: RPCObject(txHash), convertWith: { try EthTransactionReceipt($0,$1) } ) + } + + +} +/// transaction to sign +public struct EthTransaction { + /// receipient of the transaction. + public var to: String + + /// sender of the address (if not sepcified, the first signer will be the sender) + public var from: String + + /// value in wei to send + public var value: UInt64? + + /// the gas to be send along + public var gas: UInt64? + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64? + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64? + + /// the data-section of the transaction + public var data: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],false)! + value = try toUInt64(obj["value"],true)! + gas = try toUInt64(obj["gas"],true)! + gasPrice = try toUInt64(obj["gasPrice"],true)! + nonce = try toUInt64(obj["nonce"],true)! + data = try toString(obj["data"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = RPCObject(from) + obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) + obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) + obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) + obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) + obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + return obj + } +} + +/// the blockdata, or in case the block with that number does not exist, `null` will be returned. +public struct EthBlockdata { + /// the block number. `null` when its pending block. + public var number: UInt64 + + /// hash of the block. `null` when its pending block. + public var hash: String + + /// hash of the parent block. + public var parentHash: String + + /// hash of the generated proof-of-work. `null` when its pending block. + public var nonce: UInt64 + + /// SHA3 of the uncles Merkle root in the block. + public var sha3Uncles: String + + /// the bloom filter for the logs of the block. `null` when its pending block. + public var logsBloom: String + + /// the root of the transaction trie of the block. + public var transactionsRoot: String + + /// the root of the final state trie of the block. + public var stateRoot: String + + /// the root of the receipts trie of the block. + public var receiptsRoot: String + + /// the address of the beneficiary to whom the mining rewards were given. + public var miner: String + + /// integer of the difficulty for this block. + public var difficulty: UInt64 + + /// integer of the total difficulty of the chain until this block. + public var totalDifficulty: UInt64 + + /// the "extra data" field of this block. + public var extraData: String + + /// integer the size of this block in bytes. + public var size: UInt64 + + /// the maximum gas allowed in this block. + public var gasLimit: UInt64 + + /// the total used gas by all transactions in this block. + public var gasUsed: UInt64 + + /// the unix timestamp for when the block was collated. + public var timestamp: UInt64 + + /// Array of transaction objects + public var transactions: [EthTransactiondata] + + /// Array of uncle hashes. + public var uncles: [String] + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + number = try toUInt64(obj["number"],false)! + hash = try toString(obj["hash"],false)! + parentHash = try toString(obj["parentHash"],false)! + nonce = try toUInt64(obj["nonce"],false)! + sha3Uncles = try toString(obj["sha3Uncles"],false)! + logsBloom = try toString(obj["logsBloom"],false)! + transactionsRoot = try toString(obj["transactionsRoot"],false)! + stateRoot = try toString(obj["stateRoot"],false)! + receiptsRoot = try toString(obj["receiptsRoot"],false)! + miner = try toString(obj["miner"],false)! + difficulty = try toUInt64(obj["difficulty"],false)! + totalDifficulty = try toUInt64(obj["totalDifficulty"],false)! + extraData = try toString(obj["extraData"],false)! + size = try toUInt64(obj["size"],false)! + gasLimit = try toUInt64(obj["gasLimit"],false)! + gasUsed = try toUInt64(obj["gasUsed"],false)! + timestamp = try toUInt64(obj["timestamp"],false)! + transactions = try toArray(obj["transactions"])!.map({ try EthTransactiondata($0,false)! }) + uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["number"] = RPCObject(number) + obj["hash"] = RPCObject(hash) + obj["parentHash"] = RPCObject(parentHash) + obj["nonce"] = RPCObject(nonce) + obj["sha3Uncles"] = RPCObject(sha3Uncles) + obj["logsBloom"] = RPCObject(logsBloom) + obj["transactionsRoot"] = RPCObject(transactionsRoot) + obj["stateRoot"] = RPCObject(stateRoot) + obj["receiptsRoot"] = RPCObject(receiptsRoot) + obj["miner"] = RPCObject(miner) + obj["difficulty"] = RPCObject(difficulty) + obj["totalDifficulty"] = RPCObject(totalDifficulty) + obj["extraData"] = RPCObject(extraData) + obj["size"] = RPCObject(size) + obj["gasLimit"] = RPCObject(gasLimit) + obj["gasUsed"] = RPCObject(gasUsed) + obj["timestamp"] = RPCObject(timestamp) + return obj + } +} + +/// Array of transaction objects +public struct EthTransactiondata { + /// receipient of the transaction. + public var to: String + + /// sender or signer of the transaction + public var from: String + + /// value in wei to send + public var value: UInt64 + + /// the gas to be send along + public var gas: UInt64 + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64 + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64 + + /// blockHash of the block holding this transaction or `null` if still pending. + public var blockHash: String + + /// blockNumber of the block holding this transaction or `null` if still pending. + public var blockNumber: UInt64 + + /// transactionHash + public var hash: String + + /// data of the transaaction + public var input: String + + /// index of the transaaction in the block + public var transactionIndex: UInt64 + + /// recovery-byte of the signature + public var v: String + + /// x-value of the EC-Point of the signature + public var r: String + + /// y-value of the EC-Point of the signature + public var s: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],false)! + value = try toUInt64(obj["value"],false)! + gas = try toUInt64(obj["gas"],false)! + gasPrice = try toUInt64(obj["gasPrice"],false)! + nonce = try toUInt64(obj["nonce"],false)! + blockHash = try toString(obj["blockHash"],false)! + blockNumber = try toUInt64(obj["blockNumber"],false)! + hash = try toString(obj["hash"],false)! + input = try toString(obj["input"],false)! + transactionIndex = try toUInt64(obj["transactionIndex"],false)! + v = try toString(obj["v"],false)! + r = try toString(obj["r"],false)! + s = try toString(obj["s"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = RPCObject(from) + obj["value"] = RPCObject(value) + obj["gas"] = RPCObject(gas) + obj["gasPrice"] = RPCObject(gasPrice) + obj["nonce"] = RPCObject(nonce) + obj["blockHash"] = RPCObject(blockHash) + obj["blockNumber"] = RPCObject(blockNumber) + obj["hash"] = RPCObject(hash) + obj["input"] = RPCObject(input) + obj["transactionIndex"] = RPCObject(transactionIndex) + obj["v"] = RPCObject(v) + obj["r"] = RPCObject(r) + obj["s"] = RPCObject(s) + return obj + } +} + +/// The filter criteria for the events. +public struct EthFilter { + /// Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + public var fromBlock: UInt64? + + /// Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + public var toBlock: UInt64? + + /// Contract address or a list of addresses from which logs should originate. + public var address: String? + + /// Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. + public var topics: [String]? + + /// With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. + public var blockhash: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + fromBlock = try toUInt64(obj["fromBlock"],true)! + toBlock = try toUInt64(obj["toBlock"],true)! + address = try toString(obj["address"],true)! + if let topics = try toArray(obj["topics"],true) { + self.topics = try topics.map({ try toString($0,true)! }) + } else { + self.topics = nil + } + blockhash = try toString(obj["blockhash"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["fromBlock"] = fromBlock == nil ? RPCObject.none : RPCObject(fromBlock!) + obj["toBlock"] = toBlock == nil ? RPCObject.none : RPCObject(toBlock!) + obj["address"] = address == nil ? RPCObject.none : RPCObject(address!) + obj["blockhash"] = blockhash == nil ? RPCObject.none : RPCObject(blockhash!) + return obj + } +} + +/// the transactionReceipt +public struct EthTransactionReceipt { + /// the blockNumber + public var blockNumber: UInt64 + + /// blockhash if ther containing block + public var blockHash: String + + /// the deployed contract in case the tx did deploy a new contract + public var contractAddress: String + + /// gas used for all transaction up to this one in the block + public var cumulativeGasUsed: UInt64 + + /// gas used by this transaction. + public var gasUsed: UInt64 + + /// array of events created during execution of the tx + public var logs: EthLogs + + /// bloomfilter used to detect events for `eth_getLogs` + public var logsBloom: String + + /// error-status of the tx. 0x1 = success 0x0 = failure + public var status: UInt64 + + /// requested transactionHash + public var transactionHash: String + + /// transactionIndex within the containing block. + public var transactionIndex: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockNumber = try toUInt64(obj["blockNumber"],false)! + blockHash = try toString(obj["blockHash"],false)! + contractAddress = try toString(obj["contractAddress"],false)! + cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! + gasUsed = try toUInt64(obj["gasUsed"],false)! + logs = try EthLogs(obj["logs"],false)! + logsBloom = try toString(obj["logsBloom"],false)! + status = try toUInt64(obj["status"],false)! + transactionHash = try toString(obj["transactionHash"],false)! + transactionIndex = try toUInt64(obj["transactionIndex"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockNumber"] = RPCObject(blockNumber) + obj["blockHash"] = RPCObject(blockHash) + obj["contractAddress"] = RPCObject(contractAddress) + obj["cumulativeGasUsed"] = RPCObject(cumulativeGasUsed) + obj["gasUsed"] = RPCObject(gasUsed) + obj["logsBloom"] = RPCObject(logsBloom) + obj["status"] = RPCObject(status) + obj["transactionHash"] = RPCObject(transactionHash) + obj["transactionIndex"] = RPCObject(transactionIndex) + return obj + } +} + +/// array of events created during execution of the tx +public struct EthLogs { + /// the address triggering the event. + public var address: String + + /// the blockNumber + public var blockNumber: UInt64 + + /// blockhash if ther containing block + public var blockHash: String + + /// abi-encoded data of the event (all non indexed fields) + public var data: String + + /// the index of the even within the block. + public var logIndex: UInt64 + + /// the reorg-status of the event. + public var removed: Bool + + /// array of 32byte-topics of the indexed fields. + public var topics: String + + /// requested transactionHash + public var transactionHash: String + + /// transactionIndex within the containing block. + public var transactionIndex: UInt64 + + /// index of the event within the transaction. + public var transactionLogIndex: UInt64 + + /// mining-status + public var type: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + address = try toString(obj["address"],false)! + blockNumber = try toUInt64(obj["blockNumber"],false)! + blockHash = try toString(obj["blockHash"],false)! + data = try toString(obj["data"],false)! + logIndex = try toUInt64(obj["logIndex"],false)! + removed = try toBool(obj["removed"],false)! + topics = try toString(obj["topics"],false)! + transactionHash = try toString(obj["transactionHash"],false)! + transactionIndex = try toUInt64(obj["transactionIndex"],false)! + transactionLogIndex = try toUInt64(obj["transactionLogIndex"],false)! + type = try toString(obj["type"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["address"] = RPCObject(address) + obj["blockNumber"] = RPCObject(blockNumber) + obj["blockHash"] = RPCObject(blockHash) + obj["data"] = RPCObject(data) + obj["logIndex"] = RPCObject(logIndex) + obj["removed"] = RPCObject(removed) + obj["topics"] = RPCObject(topics) + obj["transactionHash"] = RPCObject(transactionHash) + obj["transactionIndex"] = RPCObject(transactionIndex) + obj["transactionLogIndex"] = RPCObject(transactionLogIndex) + obj["type"] = RPCObject(type) + return obj + } +} + +/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). +public struct EthTx { + /// address of the contract + public var to: String + + /// sender of the address + public var from: String? + + /// value in wei to send + public var value: UInt64? + + /// the gas to be send along + public var gas: UInt64? + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64? + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64? + + /// the data-section of the transaction, which includes the functionhash and the abi-encoded arguments + public var data: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],true)! + value = try toUInt64(obj["value"],true)! + gas = try toUInt64(obj["gas"],true)! + gasPrice = try toUInt64(obj["gasPrice"],true)! + nonce = try toUInt64(obj["nonce"],true)! + data = try toString(obj["data"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = from == nil ? RPCObject.none : RPCObject(from!) + obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) + obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) + obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) + obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) + obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/API/In3API.swift b/swift/Sources/In3/API/In3API.swift new file mode 100644 index 000000000..b211d0515 --- /dev/null +++ b/swift/Sources/In3/API/In3API.swift @@ -0,0 +1,483 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// There are also some Incubed specific rpc-methods, which will help the clients to bootstrap and update the nodeLists. +/// +/// +/// The incubed client itself offers special RPC-Methods, which are mostly handled directly inside the client: +/// +public class In3API { + internal var in3: In3 + + /// initialiazes the In3 API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. + /// - Parameter signature : the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. + /// - Parameter params : a array of arguments. the number of arguments must match the arguments in the signature. + /// - Returns: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. + public func abiEncode(signature: String, params: [AnyObject]) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_abiEncode",params: RPCObject(signature), RPCObject(params), convertWith: toString ) + } + + /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. + /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. + /// - Parameter data : the data to decode (usually the result of a eth_call) + /// - Returns: a array with the values after decodeing. + public func abiDecode(signature: String, data: String) throws -> [RPCObject] { + return try execLocalAndConvert(in3: in3, method: "in3_abiDecode",params: RPCObject(signature), RPCObject(data), convertWith: { try toArray($0,$1)! } ) + } + + /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) + /// - Parameter address : the address to convert. + /// - Parameter useChainId : if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) + /// - Returns: the address-string using the upper/lowercase hex characters. + public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress",params: RPCObject(address),useChainId == nil ? RPCObject.none : RPCObject(useChainId!), convertWith: toString ) + } + + /// resolves a ens-name. + /// the domain names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. + /// For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. + /// + /// - Parameter name : the domain name UTS46 compliant string. + /// - Parameter field : the required data, which could be one of ( `addr` - the address, `resolver` - the address of the resolver, `hash` - the namehash, `owner` - the owner of the domain) + /// - Returns: the value of the specified field + public func ens(name: String, field: String? = "addr") -> Future { + return execAndConvert(in3: in3, method: "in3_ens",params: RPCObject(name),field == nil ? RPCObject.none : RPCObject(field!), convertWith: toString ) + } + + /// converts the given value into wei. + /// - Parameter value : the value, which may be floating number as string + /// - Parameter unit : the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + /// - Returns: the value in wei as hex. + public func toWei(value: String, unit: String? = "eth") throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_toWei",params: RPCObject(value),unit == nil ? RPCObject.none : RPCObject(unit!), convertWith: toString ) + } + + /// converts a given uint (also as hex) with a wei-value into a specified unit. + /// - Parameter value : the value in wei + /// - Parameter unit : the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + /// - Parameter digits : fix number of digits after the comma. If left out, only as many as needed will be included. + /// - Returns: the value as string. + public func fromWei(value: String, unit: String, digits: UInt64? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_fromWei",params: RPCObject(value), RPCObject(unit),digits == nil ? RPCObject.none : RPCObject(digits!), convertWith: toString ) + } + + /// extracts the address from a private key. + /// - Parameter pk : the 32 bytes private key as hex. + /// - Returns: the address + public func pk2address(pk: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_pk2address",params: RPCObject(pk), convertWith: toString ) + } + + /// extracts the public key from a private key. + /// - Parameter pk : the 32 bytes private key as hex. + /// - Returns: the public key as 64 bytes + public func pk2public(pk: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_pk2public",params: RPCObject(pk), convertWith: toString ) + } + + /// extracts the public key and address from signature. + /// - Parameter msg : the message the signature is based on. + /// - Parameter sig : the 65 bytes signature as hex. + /// - Parameter sigtype : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw` + /// - Returns: the extracted public key and address + public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> In3Ecrecover { + return try execLocalAndConvert(in3: in3, method: "in3_ecrecover",params: RPCObject(msg), RPCObject(sig),sigtype == nil ? RPCObject.none : RPCObject(sigtype!), convertWith: { try In3Ecrecover($0,$1) } ) + } + + /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. + /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + /// - Returns: the unsigned raw transaction as hex. + public func prepareTx(tx: In3Transaction) -> Future { + return execAndConvert(in3: in3, method: "in3_prepareTx",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + } + + /// signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. + /// - Parameter tx : the raw unsigned transactiondata + /// - Parameter from : the account to sign + /// - Returns: the raw transaction with signature. + public func signTx(tx: String, from: String) -> Future { + return execAndConvert(in3: in3, method: "in3_signTx",params: RPCObject(tx), RPCObject(from), convertWith: toString ) + } + + /// signs the given data. + /// - Parameter msg : the message to sign. + /// - Parameter account : the account to sign if the account is a bytes32 it will be used as private key + /// - Parameter msgType : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data) + /// - Returns: the signature + public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { + return execAndConvert(in3: in3, method: "in3_signData",params: RPCObject(msg), RPCObject(account),msgType == nil ? RPCObject.none : RPCObject(msgType!), convertWith: { try In3SignData($0,$1) } ) + } + + /// decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. + /// - Parameter key : Keydata as object as defined in the keystorefile + /// - Parameter passphrase : the password to decrypt it. + /// - Returns: a raw private key (32 bytes) + public func decryptKey(key: String, passphrase: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_decryptKey",params: RPCObject(key), RPCObject(passphrase), convertWith: toString ) + } + + /// clears the incubed cache (usually found in the .in3-folder) + /// - Returns: true indicating the success + public func cacheClear() throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_cacheClear", convertWith: toString ) + } + + /// fetches and verifies the nodeList from a node + /// - Parameter limit : if the number is defined and >0 this method will return a partial nodeList limited to the given number. + /// - Parameter seed : this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. + /// - Parameter addresses : a optional array of addresses of signers the nodeList must include. + /// - Returns: the current nodelist + public func nodeList(limit: UInt64? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { + return execAndConvert(in3: in3, method: "in3_nodeList",params:limit == nil ? RPCObject.none : RPCObject(limit!),seed == nil ? RPCObject.none : RPCObject(seed!),addresses == nil ? RPCObject.none : RPCObject(addresses!), convertWith: { try In3NodeList($0,$1) } ) + } + + /// requests a signed blockhash from the node. + /// In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers + /// and the processising nodes will then aquire the signatures with this method from the other nodes. + /// + /// Since each node has a risk of signing a wrong blockhash and getting convicted and losing its deposit, + /// per default nodes will and should not sign blockHash of the last `minBlockHeight` (default: 6) blocks! + /// + /// - Parameter blocks : array of requested blocks. + /// - Returns: the Array with signatures of all the requires blocks. + public func sign(blocks: In3Blocks) -> Future { + return execAndConvert(in3: in3, method: "in3_sign",params: RPCObject(blocks.toRPCDict()), convertWith: { try In3Sign($0,$1) } ) + } + + /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. + /// - Parameter address : address of whitelist contract + /// - Returns: the whitelisted addresses + public func whitelist(address: String) -> Future { + return execAndConvert(in3: in3, method: "in3_whitelist",params: RPCObject(address), convertWith: { try In3Whitelist($0,$1) } ) + } + + /// adds a raw private key as signer, which allows signing transactions. + /// - Parameter pk : the 32byte long private key as hex string. + /// - Returns: the address of given key. + public func addRawKey(pk: String) -> Future { + return execAndConvert(in3: in3, method: "in3_addRawKey",params: RPCObject(pk), convertWith: toString ) + } + + /// returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. + /// - Returns: the array of addresses of all registered signers. + public func accounts() -> Future { + return execAndConvert(in3: in3, method: "eth_accounts", convertWith: toString ) + } + + +} +/// the extracted public key and address +public struct In3Ecrecover { + /// the public Key of the signer (64 bytes) + public var publicKey: String + + /// the address + public var address: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + publicKey = try toString(obj["publicKey"],false)! + address = try toString(obj["address"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["publicKey"] = RPCObject(publicKey) + obj["address"] = RPCObject(address) + return obj + } +} + +/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). +public struct In3Transaction { + /// receipient of the transaction. + public var to: String + + /// sender of the address (if not sepcified, the first signer will be the sender) + public var from: String + + /// value in wei to send + public var value: UInt64? + + /// the gas to be send along + public var gas: UInt64? + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64? + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64? + + /// the data-section of the transaction + public var data: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],false)! + value = try toUInt64(obj["value"],true)! + gas = try toUInt64(obj["gas"],true)! + gasPrice = try toUInt64(obj["gasPrice"],true)! + nonce = try toUInt64(obj["nonce"],true)! + data = try toString(obj["data"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = RPCObject(from) + obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) + obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) + obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) + obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) + obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + return obj + } +} + +/// the signature +public struct In3SignData { + /// original message used + public var message: String + + /// the hash the signature is based on + public var messageHash: String + + /// the signature (65 bytes) + public var signature: String + + /// the x-value of the EC-Point + public var r: String + + /// the y-value of the EC-Point + public var s: String + + /// the recovery value (0|1) + 27 + public var v: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + message = try toString(obj["message"],false)! + messageHash = try toString(obj["messageHash"],false)! + signature = try toString(obj["signature"],false)! + r = try toString(obj["r"],false)! + s = try toString(obj["s"],false)! + v = try toString(obj["v"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["message"] = RPCObject(message) + obj["messageHash"] = RPCObject(messageHash) + obj["signature"] = RPCObject(signature) + obj["r"] = RPCObject(r) + obj["s"] = RPCObject(s) + obj["v"] = RPCObject(v) + return obj + } +} + +/// the current nodelist +public struct In3NodeList { + /// a array of node definitions. + public var nodes: In3Nodes + + /// the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. + public var contract: String + + /// the registryId (32 bytes) of the contract, which is there to verify the correct contract. + public var registryId: String + + /// the blockNumber of the last change of the list (usually the last event). + public var lastBlockNumber: UInt64 + + /// the total numbers of nodes. + public var totalServer: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + nodes = try In3Nodes(obj["nodes"],false)! + contract = try toString(obj["contract"],false)! + registryId = try toString(obj["registryId"],false)! + lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! + totalServer = try toUInt64(obj["totalServer"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["contract"] = RPCObject(contract) + obj["registryId"] = RPCObject(registryId) + obj["lastBlockNumber"] = RPCObject(lastBlockNumber) + obj["totalServer"] = RPCObject(totalServer) + return obj + } +} + +/// a array of node definitions. +public struct In3Nodes { + /// the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. + public var url: String + + /// the address of the signer + public var address: String + + /// the index within the nodeList of the contract + public var index: UInt64 + + /// the stored deposit + public var deposit: UInt64 + + /// the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) + public var props: UInt64 + + /// the time in seconds describing how long the deposit would be locked when trying to unregister a node. + public var timeout: UInt64 + + /// unix timestamp in seconds when the node has registered. + public var registerTime: UInt64 + + /// the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. + public var weight: UInt64 + + /// a hash value containing the above values. + /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof + /// per node instead of verifying each property as its own storage value. + /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` + /// + public var proofHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + url = try toString(obj["url"],false)! + address = try toString(obj["address"],false)! + index = try toUInt64(obj["index"],false)! + deposit = try toUInt64(obj["deposit"],false)! + props = try toUInt64(obj["props"],false)! + timeout = try toUInt64(obj["timeout"],false)! + registerTime = try toUInt64(obj["registerTime"],false)! + weight = try toUInt64(obj["weight"],false)! + proofHash = try toString(obj["proofHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["url"] = RPCObject(url) + obj["address"] = RPCObject(address) + obj["index"] = RPCObject(index) + obj["deposit"] = RPCObject(deposit) + obj["props"] = RPCObject(props) + obj["timeout"] = RPCObject(timeout) + obj["registerTime"] = RPCObject(registerTime) + obj["weight"] = RPCObject(weight) + obj["proofHash"] = RPCObject(proofHash) + return obj + } +} + +/// array of requested blocks. +public struct In3Blocks { + /// the blockNumber to sign + public var blockNumber: UInt64 + + /// the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. + public var hash: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockNumber = try toUInt64(obj["blockNumber"],false)! + hash = try toString(obj["hash"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockNumber"] = RPCObject(blockNumber) + obj["hash"] = hash == nil ? RPCObject.none : RPCObject(hash!) + return obj + } +} + +/// the Array with signatures of all the requires blocks. +public struct In3Sign { + /// the blockhash which was signed. + public var blockHash: String + + /// the blocknumber + public var block: UInt64 + + /// r-value of the signature + public var r: String + + /// s-value of the signature + public var s: String + + /// v-value of the signature + public var v: String + + /// the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` + public var msgHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockHash = try toString(obj["blockHash"],false)! + block = try toUInt64(obj["block"],false)! + r = try toString(obj["r"],false)! + s = try toString(obj["s"],false)! + v = try toString(obj["v"],false)! + msgHash = try toString(obj["msgHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockHash"] = RPCObject(blockHash) + obj["block"] = RPCObject(block) + obj["r"] = RPCObject(r) + obj["s"] = RPCObject(s) + obj["v"] = RPCObject(v) + obj["msgHash"] = RPCObject(msgHash) + return obj + } +} + +/// the whitelisted addresses +public struct In3Whitelist { + /// array of whitelisted nodes addresses. + public var nodes: String + + /// the blockNumber of the last change of the in3 white list event. + public var lastWhiteList: UInt64 + + /// whitelist contract address. + public var contract: String + + /// the blockNumber of the last change of the list (usually the last event). + public var lastBlockNumber: UInt64 + + /// the total numbers of whitelist nodes. + public var totalServer: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + nodes = try toString(obj["nodes"],false)! + lastWhiteList = try toUInt64(obj["lastWhiteList"],false)! + contract = try toString(obj["contract"],false)! + lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! + totalServer = try toUInt64(obj["totalServer"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["nodes"] = RPCObject(nodes) + obj["lastWhiteList"] = RPCObject(lastWhiteList) + obj["contract"] = RPCObject(contract) + obj["lastBlockNumber"] = RPCObject(lastBlockNumber) + obj["totalServer"] = RPCObject(totalServer) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/API/IpfsAPI.swift b/swift/Sources/In3/API/IpfsAPI.swift new file mode 100644 index 000000000..0f5f1a4cb --- /dev/null +++ b/swift/Sources/In3/API/IpfsAPI.swift @@ -0,0 +1,38 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// A Node supporting IPFS must support these 2 RPC-Methods for uploading and downloading IPFS-Content. The node itself will run a ipfs-client to handle them. +/// +/// Fetching ipfs-content can be easily verified by creating the ipfs-hash based on the received data and comparing it to the requested ipfs-hash. Since there is no chance of manipulating the data, there is also no need to put a deposit or convict a node. That's why the registry-contract allows a zero-deposit fot ipfs-nodes. +/// +public class IpfsAPI { + internal var in3: In3 + + /// initialiazes the Ipfs API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// Fetches the data for a requested ipfs-hash. If the node is not able to resolve the hash or find the data a error should be reported. + /// - Parameter ipfshash : the ipfs multi hash + /// - Parameter encoding : the encoding used for the response. ( `hex` , `base64` or `utf8`) + /// - Returns: the content matching the requested hash encoded in the defined encoding. + public func get(ipfshash: String, encoding: String) -> Future { + return execAndConvert(in3: in3, method: "ipfs_get",params: RPCObject(ipfshash), RPCObject(encoding), convertWith: toString ) + } + + /// Stores ipfs-content to the ipfs network. + /// Important! As a client there is no garuantee that a node made this content available. ( just like `eth_sendRawTransaction` will only broadcast it). + /// Even if the node stores the content there is no gurantee it will do it forever. + /// + /// - Parameter data : the content encoded with the specified encoding. + /// - Parameter encoding : the encoding used for the request. ( `hex` , `base64` or `utf8`) + /// - Returns: the ipfs multi hash + public func put(data: String, encoding: String) -> Future { + return execAndConvert(in3: in3, method: "ipfs_put",params: RPCObject(data), RPCObject(encoding), convertWith: toString ) + } + + +} diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift new file mode 100644 index 000000000..8db658d27 --- /dev/null +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -0,0 +1,547 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* +/// +/// the zksync-plugin is able to handle operations to use [zksync](https://zksync.io/) like deposit transfer or withdraw. Also see the #in3-config on how to configure the zksync-server or account. +/// +/// Also in order to sign messages you need to set a signer! +/// +/// All zksync-methods can be used with `zksync_` or `zk_` prefix. +/// +public class ZksyncAPI { + internal var in3: In3 + + /// initialiazes the Zksync API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// returns the contract address + /// - Returns: fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. + public func contractAddress() -> Future { + return execAndConvert(in3: in3, method: "zksync_contract_address", convertWith: { try ZksyncContractAddress($0,$1) } ) + } + + /// returns the list of all available tokens + /// - Returns: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. + public func tokens() -> Future { + return execAndConvert(in3: in3, method: "zksync_tokens", convertWith: { try ZksyncTokens($0,$1) } ) + } + + /// returns account_info from the server + /// - Parameter address : the account-address. if not specified, the client will try to use its own address based on the signer config. + /// - Returns: the current state of the requested account. + public func accountInfo(address: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_account_info",params:address == nil ? RPCObject.none : RPCObject(address!), convertWith: { try ZksyncAccountInfo($0,$1) } ) + } + + /// returns the state or receipt of the the zksync-tx + /// - Parameter tx : the txHash of the send tx + /// - Returns: the current state of the requested tx. + public func txInfo(tx: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_tx_info",params: RPCObject(tx), convertWith: { try ZksyncTxInfo($0,$1) } ) + } + + /// sets the signerkey based on the current pk or as configured in the config. + /// You can specify the key by either + /// - setting a signer ( the sync key will be derrived through a signature ) + /// - setting the seed directly ( `sync_key` in the config) + /// - setting the `musig_pub_keys` to generate the pubKeyHash based on them + /// - setting the `create2` options and the sync-key will generate the account based on the pubKeyHash + /// + /// + /// we support 3 different signer types (`signer_type` in the `zksync` config) : + /// + /// 1. `pk` - Simple Private Key + /// If a signer is set (for example by setting the pk), incubed will derrive the sync-key through a signature and use it + /// 2. `contract` - Contract Signature + /// In this case a preAuth-tx will be send on L1 using the signer. If this contract is a mutisig, you should make sure, you have set the account explicitly in the config and also activate the multisig-plugin, so the transaction will be send through the multisig. + /// 3. `create2` - Create2 based Contract + /// + /// - Parameter token : the token to pay the gas (either the symbol or the address) + /// - Returns: the pubKeyHash, if it was executed successfully + public func setKey(token: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_set_key",params: RPCObject(token), convertWith: toString ) + } + + /// returns the current PubKeyHash based on the configuration set. + /// - Parameter pubKey : the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) + /// - Returns: the pubKeyHash + public func pubkeyhash(pubKey: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_pubkeyhash",params:pubKey == nil ? RPCObject.none : RPCObject(pubKey!), convertWith: toString ) + } + + /// returns the current packed PubKey based on the config set. + /// + /// If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. + /// + /// - Returns: the pubKey + public func pubkey() -> Future { + return execAndConvert(in3: in3, method: "zksync_pubkey", convertWith: toString ) + } + + /// returns the address of the account used. + /// - Returns: the account used. + public func accountAddress() -> Future { + return execAndConvert(in3: in3, method: "zksync_account_address", convertWith: toString ) + } + + /// returns the schnorr musig signature based on the current config. + /// + /// This also supports signing with multiple keys. In this case the configuration needs to sets the urls of the other keys, so the client can then excange all data needed in order to create the combined signature. + /// when exchanging the data with other keys, all known data will be send using `zk_sign` as method, but instead of the raw message a object with those data will be passed. + /// + /// - Parameter message : the message to sign + /// - Returns: The return value are 96 bytes of signature: /// - `[0...32]` packed public key /// - `[32..64]` r-value /// - `[64..96]` s-value /// + public func sign(message: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_sign",params: RPCObject(message), convertWith: toString ) + } + + /// returns 0 or 1 depending on the successfull verification of the signature. + /// + /// if the `musig_pubkeys` are set it will also verify against the given public keys list. + /// + /// - Parameter message : the message which was supposed to be signed + /// - Parameter signature : the signature (96 bytes) + /// - Returns: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. + public func verify(message: String, signature: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_verify",params: RPCObject(message), RPCObject(signature), convertWith: toUInt64 ) + } + + /// returns the state or receipt of the the PriorityOperation + /// - Parameter opId : the opId of a layer-operstion (like depositing) + public func ethopInfo(opId: UInt64) -> Future { + return execAndConvert(in3: in3, method: "zksync_ethop_info",params: RPCObject(opId), convertWith: toString ) + } + + /// returns current token-price + /// - Parameter token : Symbol or address of the token + /// - Returns: the token price + public func getTokenPrice(token: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_get_token_price",params: RPCObject(token), convertWith: toDouble ) + } + + /// calculates the fees for a transaction. + /// - Parameter txType : The Type of the transaction "Withdraw" or "Transfer" + /// - Parameter address : the address of the receipient + /// - Parameter token : the symbol or address of the token to pay + /// - Returns: the fees split up into single values + public func getTxFee(txType: String, address: String, token: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_get_tx_fee",params: RPCObject(txType), RPCObject(address), RPCObject(token), convertWith: { try ZksyncTxFee($0,$1) } ) + } + + /// returns private key used for signing zksync-transactions + /// - Returns: the raw private key configured based on the signers seed + public func syncKey() -> Future { + return execAndConvert(in3: in3, method: "zksync_sync_key", convertWith: toString ) + } + + /// sends a deposit-transaction and returns the opId, which can be used to tradck progress. + /// - Parameter amount : the value to deposit in wei (or smallest token unit) + /// - Parameter token : the token as symbol or address + /// - Parameter approveDepositAmountForERC20 : if true and in case of an erc20-token, the client will send a approve transaction first, otherwise it is expected to be already approved. + /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. + /// - Returns: the opId. You can use `zksync_ethop_info` to follow the state-changes. + public func deposit(amount: UInt64, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_deposit",params: RPCObject(amount), RPCObject(token),approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject(approveDepositAmountForERC20!),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toUInt64 ) + } + + /// sends a zksync-transaction and returns data including the transactionHash. + /// - Parameter to : the receipient of the tokens + /// - Parameter amount : the value to transfer in wei (or smallest token unit) + /// - Parameter token : the token as symbol or address + /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. + /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. + public func transfer(to: String, amount: UInt64, token: String, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_transfer",params: RPCObject(to), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + } + + /// withdraws the amount to the given `ethAddress` for the given token. + /// - Parameter ethAddress : the receipient of the tokens in L1 + /// - Parameter amount : the value to transfer in wei (or smallest token unit) + /// - Parameter token : the token as symbol or address + /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. + /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. + public func withdraw(ethAddress: String, amount: UInt64, token: String, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_withdraw",params: RPCObject(ethAddress), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + } + + /// withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. + /// - Parameter token : the token as symbol or address + /// - Returns: the transactionReceipt + public func emergencyWithdraw(token: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_emergency_withdraw",params: RPCObject(token), convertWith: { try ZksyncTransactionReceipt($0,$1) } ) + } + + /// calculate the public key based on multiple public keys signing together using schnorr musig signatures. + /// - Parameter pubkeys : concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` + /// - Returns: the compact public Key + public func aggregatePubkey(pubkeys: String) -> Future { + return execAndConvert(in3: in3, method: "zksync_aggregate_pubkey",params: RPCObject(pubkeys), convertWith: toString ) + } + + +} +/// fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. +public struct ZksyncContractAddress { + /// the address of the govement contract + public var govContract: String + + /// the address of the main contract + public var mainContract: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + govContract = try toString(obj["govContract"],false)! + mainContract = try toString(obj["mainContract"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["govContract"] = RPCObject(govContract) + obj["mainContract"] = RPCObject(mainContract) + return obj + } +} + +/// a array of tokens-definitions. This request also caches them and will return the results from cahe if available. +public struct ZksyncTokens { + /// the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) + public var address: String + + /// decimals to be used when formating it for human readable representation. + public var decimals: UInt64 + + /// id which will be used when encoding the token. + public var id: UInt64 + + /// symbol for the token + public var symbol: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + address = try toString(obj["address"],false)! + decimals = try toUInt64(obj["decimals"],false)! + id = try toUInt64(obj["id"],false)! + symbol = try toString(obj["symbol"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["address"] = RPCObject(address) + obj["decimals"] = RPCObject(decimals) + obj["id"] = RPCObject(id) + obj["symbol"] = RPCObject(symbol) + return obj + } +} + +/// the current state of the requested account. +public struct ZksyncAccountInfo { + /// the address of the account + public var address: String + + /// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. + public var commited: ZksyncCommited + + /// the state of all depositing-tx. + public var depositing: ZksyncDepositing + + /// the assigned id of the account, which will be used when encoding it into the rollup. + public var id: UInt64 + + /// the state after the rollup was verified in L1. + public var verified: ZksyncVerified + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + address = try toString(obj["address"],false)! + commited = try ZksyncCommited(obj["commited"],false)! + depositing = try ZksyncDepositing(obj["depositing"],false)! + id = try toUInt64(obj["id"],false)! + verified = try ZksyncVerified(obj["verified"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["address"] = RPCObject(address) + obj["id"] = RPCObject(id) + return obj + } +} + +/// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. +public struct ZksyncCommited { + /// the token-balance + public var balances: UInt64 + + /// the nonce or transaction count. + public var nonce: UInt64 + + /// the pubKeyHash set for the requested account or `0x0000...` if not set yet. + public var pubKeyHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + balances = try toUInt64(obj["balances"],false)! + nonce = try toUInt64(obj["nonce"],false)! + pubKeyHash = try toString(obj["pubKeyHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["balances"] = RPCObject(balances) + obj["nonce"] = RPCObject(nonce) + obj["pubKeyHash"] = RPCObject(pubKeyHash) + return obj + } +} + +/// the state of all depositing-tx. +public struct ZksyncDepositing { + /// the token-values. + public var balances: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + balances = try toUInt64(obj["balances"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["balances"] = RPCObject(balances) + return obj + } +} + +/// the state after the rollup was verified in L1. +public struct ZksyncVerified { + /// the token-balances. + public var balances: UInt64 + + /// the nonce or transaction count. + public var nonce: UInt64 + + /// the pubKeyHash set for the requested account or `0x0000...` if not set yet. + public var pubKeyHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + balances = try toUInt64(obj["balances"],false)! + nonce = try toUInt64(obj["nonce"],false)! + pubKeyHash = try toString(obj["pubKeyHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["balances"] = RPCObject(balances) + obj["nonce"] = RPCObject(nonce) + obj["pubKeyHash"] = RPCObject(pubKeyHash) + return obj + } +} + +/// the current state of the requested tx. +public struct ZksyncTxInfo { + /// the blockNumber containing the tx or `null` if still pending + public var block: UInt64 + + /// true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. + public var executed: Bool + + /// if executed, this property marks the success of the tx. + public var success: Bool + + /// if executed and failed this will include an error message + public var failReason: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + block = try toUInt64(obj["block"],false)! + executed = try toBool(obj["executed"],false)! + success = try toBool(obj["success"],false)! + failReason = try toString(obj["failReason"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["block"] = RPCObject(block) + obj["executed"] = RPCObject(executed) + obj["success"] = RPCObject(success) + obj["failReason"] = RPCObject(failReason) + return obj + } +} + +/// the fees split up into single values +public struct ZksyncTxFee { + /// Type of the transaaction + public var feeType: String + + /// the gas for the core-transaction + public var gasFee: UInt64 + + /// current gasPrice + public var gasPriceWei: UInt64 + + /// gasTxAmount + public var gasTxAmount: UInt64 + + /// total of all fees needed to pay in order to execute the transaction + public var totalFee: UInt64 + + /// zkpFee + public var zkpFee: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + feeType = try toString(obj["feeType"],false)! + gasFee = try toUInt64(obj["gasFee"],false)! + gasPriceWei = try toUInt64(obj["gasPriceWei"],false)! + gasTxAmount = try toUInt64(obj["gasTxAmount"],false)! + totalFee = try toUInt64(obj["totalFee"],false)! + zkpFee = try toUInt64(obj["zkpFee"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["feeType"] = RPCObject(feeType) + obj["gasFee"] = RPCObject(gasFee) + obj["gasPriceWei"] = RPCObject(gasPriceWei) + obj["gasTxAmount"] = RPCObject(gasTxAmount) + obj["totalFee"] = RPCObject(totalFee) + obj["zkpFee"] = RPCObject(zkpFee) + return obj + } +} + +/// the transactionReceipt +public struct ZksyncTransactionReceipt { + /// the blockNumber + public var blockNumber: UInt64 + + /// blockhash if ther containing block + public var blockHash: String + + /// the deployed contract in case the tx did deploy a new contract + public var contractAddress: String + + /// gas used for all transaction up to this one in the block + public var cumulativeGasUsed: UInt64 + + /// gas used by this transaction. + public var gasUsed: UInt64 + + /// array of events created during execution of the tx + public var logs: ZksyncLogs + + /// bloomfilter used to detect events for `eth_getLogs` + public var logsBloom: String + + /// error-status of the tx. 0x1 = success 0x0 = failure + public var status: UInt64 + + /// requested transactionHash + public var transactionHash: String + + /// transactionIndex within the containing block. + public var transactionIndex: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockNumber = try toUInt64(obj["blockNumber"],false)! + blockHash = try toString(obj["blockHash"],false)! + contractAddress = try toString(obj["contractAddress"],false)! + cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! + gasUsed = try toUInt64(obj["gasUsed"],false)! + logs = try ZksyncLogs(obj["logs"],false)! + logsBloom = try toString(obj["logsBloom"],false)! + status = try toUInt64(obj["status"],false)! + transactionHash = try toString(obj["transactionHash"],false)! + transactionIndex = try toUInt64(obj["transactionIndex"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockNumber"] = RPCObject(blockNumber) + obj["blockHash"] = RPCObject(blockHash) + obj["contractAddress"] = RPCObject(contractAddress) + obj["cumulativeGasUsed"] = RPCObject(cumulativeGasUsed) + obj["gasUsed"] = RPCObject(gasUsed) + obj["logsBloom"] = RPCObject(logsBloom) + obj["status"] = RPCObject(status) + obj["transactionHash"] = RPCObject(transactionHash) + obj["transactionIndex"] = RPCObject(transactionIndex) + return obj + } +} + +/// array of events created during execution of the tx +public struct ZksyncLogs { + /// the address triggering the event. + public var address: String + + /// the blockNumber + public var blockNumber: UInt64 + + /// blockhash if ther containing block + public var blockHash: String + + /// abi-encoded data of the event (all non indexed fields) + public var data: String + + /// the index of the even within the block. + public var logIndex: UInt64 + + /// the reorg-status of the event. + public var removed: Bool + + /// array of 32byte-topics of the indexed fields. + public var topics: String + + /// requested transactionHash + public var transactionHash: String + + /// transactionIndex within the containing block. + public var transactionIndex: UInt64 + + /// index of the event within the transaction. + public var transactionLogIndex: UInt64 + + /// mining-status + public var type: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + address = try toString(obj["address"],false)! + blockNumber = try toUInt64(obj["blockNumber"],false)! + blockHash = try toString(obj["blockHash"],false)! + data = try toString(obj["data"],false)! + logIndex = try toUInt64(obj["logIndex"],false)! + removed = try toBool(obj["removed"],false)! + topics = try toString(obj["topics"],false)! + transactionHash = try toString(obj["transactionHash"],false)! + transactionIndex = try toUInt64(obj["transactionIndex"],false)! + transactionLogIndex = try toUInt64(obj["transactionLogIndex"],false)! + type = try toString(obj["type"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["address"] = RPCObject(address) + obj["blockNumber"] = RPCObject(blockNumber) + obj["blockHash"] = RPCObject(blockHash) + obj["data"] = RPCObject(data) + obj["logIndex"] = RPCObject(logIndex) + obj["removed"] = RPCObject(removed) + obj["topics"] = RPCObject(topics) + obj["transactionHash"] = RPCObject(transactionHash) + obj["transactionIndex"] = RPCObject(transactionIndex) + obj["transactionLogIndex"] = RPCObject(transactionLogIndex) + obj["type"] = RPCObject(type) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index b8e2e7d95..065116f48 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -35,9 +35,15 @@ public class In3 { } } + /// Execute a request directly and local. + /// This works only for requests which do not need to be send to a server. + public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { + return try execLocal(method, params) + } + /// Execute a request directly and local. /// This works only for requests which do not need to be send to a server. - public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { + public func execLocal(_ method: String, _ params: [RPCObject]) throws -> RPCObject { let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))) let rawResult = executeJSON(String(decoding: jsonReqData, as: UTF8.self)) let response = try JSONDecoder().decode(JSONResponse.self, from: rawResult.data(using: .utf8)!) diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift index 34be1da38..897d67c46 100644 --- a/swift/Sources/In3/Utils/Convert.swift +++ b/swift/Sources/In3/Utils/Convert.swift @@ -30,6 +30,62 @@ internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt return nil } +/// converts a RPC-Object to UInt64 or throws +internal func toInt(_ data:RPCObject?, _ optional:Bool = true) throws -> Int?{ + if let data = data { + switch data { + case let .integer(val): + return val + case let .string(val): + if let intVal = Int(val) { + return intVal + } else if val.hasPrefix("0x"), let intVal = Int(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { + return intVal + } else { + throw IncubedError.config(message: "Can not convert '\(val)' to int") + } + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for Int") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + +/// converts a RPC-Object to Double or throws +internal func toDouble(_ data:RPCObject?, _ optional:Bool = true) throws -> Double?{ + if let data = data { + switch data { + case let .integer(val): + return Double(val) + case let .double(val): + return val + case let .string(val): + if let intVal = Double(val) { + return intVal + } else { + throw IncubedError.config(message: "Can not convert '\(val)' to int") + } + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for Double") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + /// converts a RPC-Object to Bool or throws internal func toBool(_ data:RPCObject?, _ optional:Bool = true) throws -> Bool?{ if let data = data { @@ -166,3 +222,9 @@ internal func execAndConvertOptional(in3:In3, method: String, params: RPC + +/// executes a rpc-request and converts the result as non optional. (will return a rejected promise if it is `nil`) +internal func execLocalAndConvert(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) throws -> Type { + let res = try in3.execLocal(method, params) + return try convertWith(res,false)! +} diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index 4f18dc3e1..944cce67a 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -273,6 +273,37 @@ public enum RPCObject: Equatable { /// a JSON-Object represented as Dictionary with properties as keys and their values as RPCObjects case dictionary([String: RPCObject]) + /// Wrap a String as Value + public init(_ value: AnyObject) { + switch value { + case let val as UInt64: + self = .integer(Int(val)) + case let val as Int: + self = .integer(val) + case let val as Double: + self = .double(val) + case let val as String: + self = .string(val) + case let val as Bool: + self = .bool(val) + case nil: + self = .none + case let val as [AnyObject]: + self = .list(val.map { RPCObject($0) }) + case let val as [String]: + self = .list(val.map { RPCObject($0) }) + case let val as [String:AnyObject]: + self = .dictionary(val.mapValues({ RPCObject($0) })) + default: + self = .none + } + } + + /// Wrap a String as Value + public init(_ array: [AnyObject]) { + self = .list(array.map({ RPCObject($0)})) + } + /// Wrap a String as Value public init(_ value: String) { self = .string(value) @@ -283,6 +314,11 @@ public enum RPCObject: Equatable { self = .integer(value) } + /// Wrap a Integer as Value + public init(_ value: UInt64) { + self = .integer(Int(value)) + } + /// Wrap a Double as Value public init(_ value: Double) { self = .double(value) diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 9c114595c..288e342c0 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -45,13 +45,14 @@ final class In3Tests: XCTestCase { let expect = XCTestExpectation(description: "Should get a hash-value") // let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) let in3 = try In3(In3Config(chainId: "mainnet")) - Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { + + EthAPI(in3).getTransactionReceipt(txHash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { switch $0 { case let .failure(err): print(err.localizedDescription) case let .success( val ): if let tx = val { - print("txhash : ",tx.hash) + print("txIndex : ",tx.transactionIndex) } else { print("on tx found ") } diff --git a/swift/docs/1_intro.md b/swift/docs/1_intro.md index 034747f5d..717f44fd3 100644 --- a/swift/docs/1_intro.md +++ b/swift/docs/1_intro.md @@ -31,8 +31,3 @@ Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1 } }) ``` - -## Classes - - - From 818dcaad074d6eb68c230c36f83732cc410deb02 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:11:27 +0200 Subject: [PATCH 104/221] format --- c/src/cmd/in3/args.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 53c560f3c..534eb5ab3 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,7 +2,7 @@ #include -const char* bool_props[]={ "includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ From 32b9c3db37b88dbcca247f05161b2f50d9e3cea2 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:23:49 +0200 Subject: [PATCH 105/221] fix format --- scripts/build_rpc_docu.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index d2bc1ef68..41f94cecb 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -137,6 +137,8 @@ for (const s of Object.keys(docs).sort()) { for (const rpc of Object.keys(rpcs).sort()) { const def = rpcs[rpc] + def.returns = def.returns || def.result + def.result = def.returns || def.result let z = " '" + rpc + ': ' + short_descr((def.descr || (def.alias && rpcs[def.alias].descr) || '')) rpc_doc.push('### ' + rpc + '\n\n') @@ -232,5 +234,5 @@ Object.keys(main_conf.rpc).forEach(k => { fs.writeFileSync('_in3.sh', zsh_complete.replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) fs.writeFileSync(doc_dir + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) -fs.writeFileSync('../c/src/cmd/in3/args.h', '// This is a generated file, please don\'t edit it manually!\n\n#include \n\nconst char* bool_props[]={ ' + bool_props.map(_ => '"' + _ + '", ').join('') + ' NULL};\n\nconst char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) +fs.writeFileSync('../c/src/cmd/in3/args.h', '// This is a generated file, please don\'t edit it manually!\n\n#include \n\nconst char* bool_props[] = {' + bool_props.map(_ => '"' + _ + '", ').join('') + 'NULL};\n\nconst char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) From c7bd5f0007f5697a7167579c511dffad3b59f473 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 09:39:13 +0200 Subject: [PATCH 106/221] fix balances mapping --- scripts/build_rpc_docu.js | 5 +++-- scripts/generator/swift.js | 16 ++++++++++++++-- swift/Sources/In3/API/ZksyncAPI.swift | 19 ++++++------------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 41f94cecb..f6b037c61 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -133,8 +133,6 @@ for (const s of Object.keys(docs).sort()) { if (rdescr) rpc_doc.push(rdescr + '\n') delete rpcs.descr - swift.generateAPI(s, rpcs, rdescr, types) - for (const rpc of Object.keys(rpcs).sort()) { const def = rpcs[rpc] def.returns = def.returns || def.result @@ -215,6 +213,9 @@ for (const s of Object.keys(docs).sort()) { z += "'" zsh_cmds.push(z) } + + swift.generateAPI(s, rpcs, rdescr, types) + } handle_config(config, '') diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 480fe3abd..16632d80c 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -22,7 +22,7 @@ configs = { ] } function converterName(swiftType, asFn) { - const type = swiftType.split(/[\[\]_\?\!]+/).join('') + const type = swiftType.replace("String:", "").split(/[\[\]_\?\!]+/).join('') if (type == 'UInt64' || type == 'Double' || type == 'Bool' || type == 'String' || type == 'Int' || type == 'AnyObject') return 'to' + type if (swiftType.startsWith('[') && asFn) { if (swiftType.endsWith('?')) @@ -59,6 +59,17 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api else init += '\n ' + name + ' = try toArray(obj["' + name + '"])!.map({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' } + else if (p.key) { + if (p.optional) { + init += '\n if let ' + name + ' = try toObject(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ') {' + init += '\n self.' + name + ' = try ' + name + '.mapValues({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' + init += '\n } else {' + init += '\n self.' + name + ' = nil' + init += '\n }' + } + else + init += '\n ' + name + ' = try toObject(obj["' + name + '"])!.mapValues({ try ' + converterName(t, false) + '($0,false)! })' + } else { init += '\n ' + name + ' = try ' + converterName(t, false) + '(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ')!' if (converterName(t, false).startsWith('to')) @@ -67,7 +78,7 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api } - typesGenerated[swiftType] = content.join('\n') + '\n' + init + '\n }\n' + toRPC + '\n return obj\n }\n}' + typesGenerated[swiftType] = content.join('\n') + '\n' + init + '\n }\n' + (toRPC.indexOf('obj["') == -1 ? '' : (toRPC + '\n return obj\n }')) + '\n}' } function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { @@ -95,6 +106,7 @@ function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { if (c.array) swiftType = '[' + swiftType + ']' + if (c.key) swiftType = '[String:' + swiftType + ']' if (c.optional) swiftType += '?' return swiftType } diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift index 8db658d27..66f549987 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -276,7 +276,7 @@ public struct ZksyncAccountInfo { /// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. public struct ZksyncCommited { /// the token-balance - public var balances: UInt64 + public var balances: [String:UInt64] /// the nonce or transaction count. public var nonce: UInt64 @@ -286,14 +286,13 @@ public struct ZksyncCommited { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toUInt64(obj["balances"],false)! + balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) nonce = try toUInt64(obj["nonce"],false)! pubKeyHash = try toString(obj["pubKeyHash"],false)! } internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["balances"] = RPCObject(balances) obj["nonce"] = RPCObject(nonce) obj["pubKeyHash"] = RPCObject(pubKeyHash) return obj @@ -303,24 +302,19 @@ public struct ZksyncCommited { /// the state of all depositing-tx. public struct ZksyncDepositing { /// the token-values. - public var balances: UInt64 + public var balances: [String:UInt64] internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toUInt64(obj["balances"],false)! + balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) } - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["balances"] = RPCObject(balances) - return obj - } } /// the state after the rollup was verified in L1. public struct ZksyncVerified { /// the token-balances. - public var balances: UInt64 + public var balances: [String:UInt64] /// the nonce or transaction count. public var nonce: UInt64 @@ -330,14 +324,13 @@ public struct ZksyncVerified { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toUInt64(obj["balances"],false)! + balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) nonce = try toUInt64(obj["nonce"],false)! pubKeyHash = try toString(obj["pubKeyHash"],false)! } internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["balances"] = RPCObject(balances) obj["nonce"] = RPCObject(nonce) obj["pubKeyHash"] = RPCObject(pubKeyHash) return obj From 773faf7d7918958d1318da2f64ffbd46cd884adb Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 10:43:27 +0200 Subject: [PATCH 107/221] handle key-properties --- c/src/pay/zksync/rpc.yml | 6 ++++++ scripts/build_rpc_docu.js | 10 ++++++---- scripts/generator/swift.js | 16 ++++++++++++---- swift/Sources/In3/API/ZksyncAPI.swift | 24 ++++++++++++------------ 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index a8299e805..95848c1df 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -118,6 +118,7 @@ zksync: zksync_tokens: descr: returns the list of all available tokens result: + key: token symbol descr: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. type: address: @@ -285,6 +286,7 @@ zksync: response: "sync:e41d2489571d322189246dafa5ebde1f4699f498" zksync_pubkeyhash: + sync: true descr: returns the current PubKeyHash based on the configuration set. params: pubKey: @@ -300,6 +302,7 @@ zksync: zksync_pubkey: + sync: true descr: | returns the current packed PubKey based on the config set. @@ -314,6 +317,7 @@ zksync: zksync_account_address: + sync: true descr: returns the address of the account used. result: descr: the account used. @@ -350,6 +354,7 @@ zksync: response: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01" zksync_verify: + sync: true descr: | returns 0 or 1 depending on the successfull verification of the signature. @@ -571,6 +576,7 @@ zksync: transactionIndex: '0x0' zksync_aggregate_pubkey: + sync: true descr: calculate the public key based on multiple public keys signing together using schnorr musig signatures. params: pubkeys: diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index f6b037c61..0d6ea07c1 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -13,7 +13,7 @@ const { const doc_dir = process.argv[process.argv.length - 1] const main_conf = yaml.parse(fs.readFileSync('../c/src/cmd/in3/in3.yml', 'utf-8')) - +const typeName = (def, code) => (code ? '`' : '') + ((def.key ? '{key:$t}' : (def.array ? '$t[]' : "$t")) + (def.optional ? '?' : '')).replace('$t', typeof (def.type) === 'string' ? def.type : 'object') + (code ? '`' : '') const rpc_doc = [] const config_doc = [] const main_help = [] @@ -49,9 +49,10 @@ function print_object(def, pad, useNum, doc) { let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' const p = def[prop] const pt = getType(p.type, types) - if (p.type) s += ' : `' + (typeof p.type === 'string' ? p.type : 'object') + '`' + if (p.type) s += ' : ' + typeName(p, true) if (p.optional) s += ' *(optional)*' if (p.descr) s += ' - ' + p.descr + if (p.key) s += ' with ' + p.key + ' as keys in the object' if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' if (p.enum) s += '\n' + pad + 'Possible Values are:\n\n' + Object.keys(p.enum).map(v => pad + ' - `' + v + '` : ' + p.enum[v]).join('\n') + '\n' if (p.alias) s += '\n' + pad + 'The data structure of ' + prop + ' is the same as ' + link(p.alias) + '. See Details there.' @@ -79,7 +80,7 @@ function handle_config(conf, pre, title, descr) { let s = '\n' + (title ? '#' : '') + '## ' + key + '\n\n' + c.descr if (c.optional) s += ' *This config is optional.*' if (c.default) s += ' (default: `' + JSON.stringify(c.default) + '`)' - if (c.type) s += '\n\n Type: `' + (typeof c.type === 'string' ? c.type : 'object') + '`' + if (c.type) s += '\n\n Type: ' + typeName(c, true) if (c.enum) s += '\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n' config_doc.push(s) if (typeof (c.type) === 'object') { @@ -117,6 +118,7 @@ function handle_config(conf, pre, title, descr) { } } + scan('../c/src') docs.in3.in3_config.params.config.type = config rpc_doc.push('# API RPC\n\n') @@ -160,7 +162,7 @@ for (const s of Object.keys(docs).sort()) { if (def.returns) { if (def.returns.type) { - rpc_doc.push('*Returns:* ' + (typeof def.returns.type === 'string' ? ('`' + def.returns.type + '`') : '`object`') + '\n\n' + def.returns.descr + '\n') + rpc_doc.push('*Returns:* ' + typeName(def.returns, true) + '\n\n' + def.returns.descr + '\n') const pt = getType(def.returns.type, types) if (typeof pt === 'object') { rpc_doc.push('\nThe return value contains the following properties :\n') diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 16632d80c..26af14386 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -25,10 +25,18 @@ function converterName(swiftType, asFn) { const type = swiftType.replace("String:", "").split(/[\[\]_\?\!]+/).join('') if (type == 'UInt64' || type == 'Double' || type == 'Bool' || type == 'String' || type == 'Int' || type == 'AnyObject') return 'to' + type if (swiftType.startsWith('[') && asFn) { - if (swiftType.endsWith('?')) - return '{ if let array = try toArray($0,$1) { try array.map({ try ' + type + '($0,true)! }) } }' - else - return '{ try toArray($0,$1)!.map({ try ' + type + '($0,false)! }) }' + if (swiftType.indexOf(':') >= 0) { + if (swiftType.endsWith('?')) + return '{ if let dict = try toObject($0,$1) { try dict.mapValues({ try ' + type + '($0,true)! }) } }' + else + return '{ try toObject($0,$1)!.mapValues({ try ' + type + '($0,false)! }) }' + } + else { + if (swiftType.endsWith('?')) + return '{ if let array = try toArray($0,$1) { try array.map({ try ' + type + '($0,true)! }) } }' + else + return '{ try toArray($0,$1)!.map({ try ' + type + '($0,false)! }) }' + } } return asFn ? '{ try ' + type + '($0,$1) }' : type } diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift index 66f549987..adf00a3fa 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -27,8 +27,8 @@ public class ZksyncAPI { /// returns the list of all available tokens /// - Returns: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. - public func tokens() -> Future { - return execAndConvert(in3: in3, method: "zksync_tokens", convertWith: { try ZksyncTokens($0,$1) } ) + public func tokens() -> Future<[String:ZksyncTokens]> { + return execAndConvert(in3: in3, method: "zksync_tokens", convertWith: { try toObject($0,$1)!.mapValues({ try ZksyncTokens($0,false)! }) } ) } /// returns account_info from the server @@ -70,8 +70,8 @@ public class ZksyncAPI { /// returns the current PubKeyHash based on the configuration set. /// - Parameter pubKey : the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) /// - Returns: the pubKeyHash - public func pubkeyhash(pubKey: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_pubkeyhash",params:pubKey == nil ? RPCObject.none : RPCObject(pubKey!), convertWith: toString ) + public func pubkeyhash(pubKey: String? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "zksync_pubkeyhash",params:pubKey == nil ? RPCObject.none : RPCObject(pubKey!), convertWith: toString ) } /// returns the current packed PubKey based on the config set. @@ -79,14 +79,14 @@ public class ZksyncAPI { /// If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. /// /// - Returns: the pubKey - public func pubkey() -> Future { - return execAndConvert(in3: in3, method: "zksync_pubkey", convertWith: toString ) + public func pubkey() throws -> String { + return try execLocalAndConvert(in3: in3, method: "zksync_pubkey", convertWith: toString ) } /// returns the address of the account used. /// - Returns: the account used. - public func accountAddress() -> Future { - return execAndConvert(in3: in3, method: "zksync_account_address", convertWith: toString ) + public func accountAddress() throws -> String { + return try execLocalAndConvert(in3: in3, method: "zksync_account_address", convertWith: toString ) } /// returns the schnorr musig signature based on the current config. @@ -107,8 +107,8 @@ public class ZksyncAPI { /// - Parameter message : the message which was supposed to be signed /// - Parameter signature : the signature (96 bytes) /// - Returns: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. - public func verify(message: String, signature: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_verify",params: RPCObject(message), RPCObject(signature), convertWith: toUInt64 ) + public func verify(message: String, signature: String) throws -> UInt64 { + return try execLocalAndConvert(in3: in3, method: "zksync_verify",params: RPCObject(message), RPCObject(signature), convertWith: toUInt64 ) } /// returns the state or receipt of the the PriorityOperation @@ -179,8 +179,8 @@ public class ZksyncAPI { /// calculate the public key based on multiple public keys signing together using schnorr musig signatures. /// - Parameter pubkeys : concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` /// - Returns: the compact public Key - public func aggregatePubkey(pubkeys: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_aggregate_pubkey",params: RPCObject(pubkeys), convertWith: toString ) + public func aggregatePubkey(pubkeys: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "zksync_aggregate_pubkey",params: RPCObject(pubkeys), convertWith: toString ) } From b11bc1da0fe0b17d6fd0f624f9c05448ce8f8559 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 13:07:29 +0200 Subject: [PATCH 108/221] add examples to the comments --- c/src/verifier/btc/rpc.yml | 3 + c/src/verifier/eth1/basic/rpc.yml | 28 ++ scripts/check_bindings.js | 2 + scripts/generator/swift.js | 28 +- swift/Sources/In3/API/BtcAPI.swift | 343 ++++++++++++++- swift/Sources/In3/API/EthAPI.swift | 603 +++++++++++++++++++++++++- swift/Sources/In3/API/In3API.swift | 277 ++++++++++++ swift/Sources/In3/API/IpfsAPI.swift | 32 ++ swift/Sources/In3/API/ZksyncAPI.swift | 325 +++++++++++++- 9 files changed, 1621 insertions(+), 20 deletions(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index c5807b79b..3b2ca496c 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -308,6 +308,7 @@ btc: verbosity: 0 name: getblockheaderAsHex descr: returns a hex representation of the blockheader + example: '3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d' result: optional: true type: bytes @@ -417,6 +418,7 @@ btc: - params: verbosity: 0 name: getBlockAsHex + example: '3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d' descr: returns a hex representation of the block result: optional: true @@ -509,6 +511,7 @@ btc: - params: verbosity: 0 name: getRawTransactionAsHex + example: '3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d' descr: returns a hex representation of the tx result: optional: true diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 10aa5be5a..722c84278 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -194,6 +194,20 @@ eth: descr: if true the full transactions are contained in the result. type: bool result: + optional: true + options: + - params: + fullTx: false + name: getBlockByNumber + descr: returns the given Block by number with transactionHashes + result: + type: blockdataWithTxHashes + - params: + fullTx: false + name: getBlockByNumberWithTx + descr: returns the given Block by number with full transaction data + result: + type: blockdata descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. type: blockdata @@ -311,6 +325,20 @@ eth: descr: if true the full transactions are contained in the result. type: bool result: + optional: true + options: + - params: + fullTx: false + name: getBlockByHash + descr: returns the given Block by hash with transactionHashes + result: + type: blockdataWithTxHashes + - params: + fullTx: false + name: getBlockByHashWithTx + descr: returns the given Block by hash with full transaction data + result: + type: blockdata descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. type: blockdata diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 32076778a..57295c152 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -39,6 +39,7 @@ const bindings = { python: strings('../python/in3', '"'), rust: strings('../rust/in3-rs/src', '"'), dotnet: strings('../dotnet/In3', '"', '*.cs'), + swift: strings('../swift/Sources', '"'), c_api: strings('../c/src/api', '"',), autocmpl: grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]), } @@ -68,6 +69,7 @@ bindings.wasm = grep('\"^[ ]*[a-zA-Z0-9_]+[\\?]*:.*\"', '../wasm/src').map(_ => bindings.autocmpl = [] bindings.c_api = [] bindings.python = grep("\"self\\.[a-zA-Z0-9_]+\"", '../python/in3/model.py').map(_ => ((/self.([a-zA-Z0-9_]+)/gm).exec(_) || ["", ""])[1]) +bindings.swift = grep("\"var [a-zA-Z0-9_]+\"", '../swift/Sources/In3/Config.swift').map(_ => ((/var ([a-zA-Z0-9_]+)/gm).exec(_) || ["", ""])[1]) for (const conf of configs) { diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 26af14386..79839f0ed 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -186,6 +186,9 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc if (r.options) { for (option of r.options) { let rr = { ...rpc, result: { ...r, ...option.result } } + if (option.example && rr.example) rr.example = { ...rr.example, response: option.example } + if (option.params && rr.example && rr.example.request) + rr.example = { ...rr.example, request: rr.example.request.slice(0, Object.keys(rpc.params).length - Object.keys(option.params).length) } rr.params = {} for (let pp of Object.keys(rpc.params)) { rr.params[pp] = { ...rpc.params[pp] } @@ -239,7 +242,30 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc s += ' convertWith: ' + converterName(returnType, true) + ' )' s += '\n }\n' } - if (r.descr) content.push(' /// - Returns: ' + rpc.result.descr.split('\n').join(' /// ')) + if (r.descr) content.push(' /// - Returns: ' + rpc.result.descr.split('\n').join('\n /// ')) + + asArray(rpc.example).forEach(ex => { + const paramNames = Object.keys(rpc.params || {}) + let x = '\n**Example**\n\n```swift\n' + let call = camelCaseUp(api_name) + 'API(in3).' + fnName + '(' + (ex.request || []).map((_, i) => paramNames[i] + ': ' + JSON.stringify(_)).join(', ') + ')' + if (rpc.sync) { + x += 'let result = try ' + call + '\n' + x += '// result = ' + (typeof ex.response === 'object' ? '\n// ' : '') + yaml.stringify(ex.response).trim().split('\n').join('\n// ') + } + else { + x += call + ' .observe(using: {\n' + x += ' switch $0 {\n' + x += ' case let .failure(err):\n' + x += ' print("Failed because : \\(err.localizedDescription)")\n' + x += ' case let .success(val):\n' + x += ' print("result : \\(val)")\n' + x += '// result = ' + (typeof ex.response === 'object' ? '\n// ' : '') + yaml.stringify(ex.response).trim().split('\n').join('\n// ') + x += '\n }\n' + x += '}\n' + } + x += '\n```\n' + content.push(' /// ' + x.split('\n').join('\n /// ')) + }) content.push(s) } diff --git a/swift/Sources/In3/API/BtcAPI.swift b/swift/Sources/In3/API/BtcAPI.swift index 598bf77f6..b344bda45 100644 --- a/swift/Sources/In3/API/BtcAPI.swift +++ b/swift/Sources/In3/API/BtcAPI.swift @@ -27,35 +27,183 @@ public class BtcAPI { /// returns a hex representation of the blockheader /// - Parameter hash : The block hash - /// - Returns: the blockheader. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + /// - Returns: the blockheader. + /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + /// - verbose `1` or `true`: an object representing the blockheader. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getblockheaderAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d + /// } + /// } + /// + /// ``` + /// public func getblockheaderAsHex(hash: String) -> Future { return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(0), convertWith: toString ) } /// returns the blockheader /// - Parameter hash : The block hash - /// - Returns: the blockheader. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + /// - Returns: the blockheader. + /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + /// - verbose `1` or `true`: an object representing the blockheader. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getblockheader(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + /// // confirmations: 8268 + /// // height: 624958 + /// // version: 536928256 + /// // versionHex: 2000 + /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb + /// // time: 1586333924 + /// // mediantime: 1586332639 + /// // nonce: 1985217615 + /// // bits: 17143b41 + /// // difficulty: 13912524048945.91 + /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 + /// // nTx: 33 + /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 + /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 + /// } + /// } + /// + /// ``` + /// public func getblockheader(hash: String) -> Future { return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblockheader($0,$1) } ) } /// returns a hex representation of the block /// - Parameter hash : The block hash - /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + /// - Returns: the block. + /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + /// - verbose `1` or `true`: an object representing the blockheader. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getBlockAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d + /// } + /// } + /// + /// ``` + /// public func getBlockAsHex(hash: String) -> Future { return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(0), convertWith: toString ) } /// returns the block with transactionhashes /// - Parameter hash : The block hash - /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + /// - Returns: the block. + /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + /// - verbose `1` or `true`: an object representing the blockheader. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getBlock(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + /// // confirmations: 8268 + /// // height: 624958 + /// // version: 536928256 + /// // versionHex: 2000 + /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb + /// // time: 1586333924 + /// // mediantime: 1586332639 + /// // nonce: 1985217615 + /// // bits: 17143b41 + /// // difficulty: 13912524048945.91 + /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 + /// // tx: + /// // - d79ffc80e07fe9e0083319600c59d47afe69995b1357be6e5dba035675780290 + /// // - ... + /// // - 6456819bfa019ba30788620153ea9a361083cb888b3662e2ff39c0f7adf16919 + /// // nTx: 33 + /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 + /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 + /// } + /// } + /// + /// ``` + /// public func getBlock(hash: String) -> Future { return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblock($0,$1) } ) } /// returns the block with full transactions /// - Parameter hash : The block hash - /// - Returns: the block. /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader /// - verbose `1` or `true`: an object representing the blockheader. /// + /// - Returns: the block. + /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader + /// - verbose `1` or `true`: an object representing the blockheader. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getBlockWithTx(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + /// // confirmations: 8268 + /// // height: 624958 + /// // version: 536928256 + /// // versionHex: 2000 + /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb + /// // time: 1586333924 + /// // mediantime: 1586332639 + /// // nonce: 1985217615 + /// // bits: 17143b41 + /// // difficulty: 13912524048945.91 + /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 + /// // tx: + /// // - d79ffc80e07fe9e0083319600c59d47afe69995b1357be6e5dba035675780290 + /// // - ... + /// // - 6456819bfa019ba30788620153ea9a361083cb888b3662e2ff39c0f7adf16919 + /// // nTx: 33 + /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 + /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 + /// } + /// } + /// + /// ``` + /// public func getBlockWithTx(hash: String) -> Future { return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(2), convertWith: { try BtcblockWithTx($0,$1) } ) } @@ -63,7 +211,25 @@ public class BtcAPI { /// returns a hex representation of the tx /// - Parameter txid : The transaction id /// - Parameter blockhash : The block in which to look for the transaction - /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` /// - verbose `1` or `false`: an object representing the transaction. /// + /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` + /// - verbose `1` or `false`: an object representing the transaction. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getRawTransactionAsHex(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d + /// } + /// } + /// + /// ``` + /// public func getRawTransactionAsHex(txid: String, blockhash: String? = nil) -> Future { return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(0), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: toString ) } @@ -71,20 +237,124 @@ public class BtcAPI { /// returns the raw transaction /// - Parameter txid : The transaction id /// - Parameter blockhash : The block in which to look for the transaction - /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` /// - verbose `1` or `false`: an object representing the transaction. /// + /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` + /// - verbose `1` or `false`: an object representing the transaction. + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getRawTransaction(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // in_active_chain: true + /// // txid: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf + /// // hash: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf + /// // version: 1 + /// // size: 518 + /// // vsize: 518 + /// // weight: 2072 + /// // locktime: 0 + /// // vin: + /// // - txid: 0a74f6e5f99bc69af80da9f0d9878ea6afbfb5fbb2d43f1ff899bcdd641a098c + /// // vout: 0 + /// // scriptSig: + /// // asm: 30440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228cc...254874 + /// // hex: 4730440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228...254874 + /// // sequence: 4294967295 + /// // - txid: 869c5e82d4dfc3139c8a153d2ee126e30a467cf791718e6ea64120e5b19e5044 + /// // vout: 0 + /// // scriptSig: + /// // asm: 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d + /// // hex: 483045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745...f3255d + /// // sequence: 4294967295 + /// // - txid: 8a03d29a1b8ae408c94a2ae15bef8329bc3d6b04c063d36b2e8c997273fa8eff + /// // vout: 1 + /// // scriptSig: + /// // asm: 304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d1284...0045da + /// // hex: 47304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d12...0045da + /// // sequence: 4294967295 + /// // vout: + /// // - value: 0.00017571 + /// // n: 0 + /// // scriptPubKey: + /// // asm: OP_DUP OP_HASH160 53196749b85367db9443ef9a5aec25cf0bdceedf OP_EQUALVERIFY + /// // OP_CHECKSIG + /// // hex: 76a91453196749b85367db9443ef9a5aec25cf0bdceedf88ac + /// // reqSigs: 1 + /// // type: pubkeyhash + /// // addresses: + /// // - 18aPWzBTq1nzs9o86oC9m3BQbxZWmV82UU + /// // - value: 0.00915732 + /// // n: 1 + /// // scriptPubKey: + /// // asm: OP_HASH160 8bb2b4b848d0b6336cc64ea57ae989630f447cba OP_EQUAL + /// // hex: a9148bb2b4b848d0b6336cc64ea57ae989630f447cba87 + /// // reqSigs: 1 + /// // type: scripthash + /// // addresses: + /// // - 3ERfvuzAYPPpACivh1JnwYbBdrAjupTzbw + /// // hex: 01000000038c091a64ddbc99f81f3fd4b2fbb5bfafa68e8...000000 + /// // blockhash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 + /// // confirmations: 15307 + /// // time: 1586333924 + /// // blocktime: 1586333924 + /// } + /// } + /// + /// ``` + /// public func getRawTransaction(txid: String, blockhash: String? = nil) -> Future { return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(1), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: { try Btctransaction($0,$1) } ) } /// Returns the number of blocks in the longest blockchain. /// - Returns: the current blockheight + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getblockcount() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 640387 + /// } + /// } + /// + /// ``` + /// public func getblockcount() -> Future { return execAndConvert(in3: in3, method: "getblockcount", convertWith: toUInt64 ) } /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. /// - Parameter blocknumber : Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`) - /// - Returns: - `blocknumber` is a certain number: the difficulty of this block /// - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) /// + /// - Returns: - `blocknumber` is a certain number: the difficulty of this block + /// - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) + /// + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getdifficulty(blocknumber: 631910) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 15138043247082.88 + /// } + /// } + /// + /// ``` + /// public func getdifficulty(blocknumber: UInt64) -> Future { return execAndConvert(in3: in3, method: "getdifficulty",params: RPCObject(blocknumber), convertWith: toUInt64 ) } @@ -96,12 +366,69 @@ public class BtcAPI { /// - Parameter max_dap : the maximum amount of daps between 2 verified daps /// - Parameter limit : the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory /// - Returns: A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).proofTarget(target_dap: 230, verified_dap: 200, max_diff: 5, max_dap: 5, limit: 15) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // - dap: 205 + /// // block: 0x04000000e62ef28cb9793f4f9cd2a67a58c1e7b593129b9b...0ab284 + /// // final: 0x04000000cc69b68b702321adf4b0c485fdb1f3d6c1ddd140...090a5b + /// // cbtx: 0x01000000...1485ce370573be63d7cc1b9efbad3489eb57c8...000000 + /// // cbtxMerkleProof: 0xc72dffc1cb4cbeab960d0d2bdb80012acf7f9c...affcf4 + /// // - dap: 210 + /// // block: 0x0000003021622c26a4e62cafa8e434c7e083f540bccc8392...b374ce + /// // final: 0x00000020858f8e5124cd516f4d5e6a078f7083c12c48e8cd...308c3d + /// // cbtx: 0x01000000...c075061b4b6e434d696e657242332d50314861...000000 + /// // cbtxMerkleProof: 0xf2885d0bac15fca7e1644c1162899ecd43d52b...93761d + /// // - dap: 215 + /// // block: 0x000000202509b3b8e4f98290c7c9551d180eb2a463f0b978...f97b64 + /// // final: 0x0000002014c7c0ed7c33c59259b7b508bebfe3974e1c99a5...eb554e + /// // cbtx: 0x01000000...90133cf94b1b1c40fae077a7833c0fe0ccc474...000000 + /// // cbtxMerkleProof: 0x628c8d961adb157f800be7cfb03ffa1b53d3ad...ca5a61 + /// // - dap: 220 + /// // block: 0x00000020ff45c783d09706e359dcc76083e15e51839e4ed5...ddfe0e + /// // final: 0x0000002039d2f8a1230dd0bee50034e8c63951ab812c0b89...5670c5 + /// // cbtx: 0x01000000...b98e79fb3e4b88aefbc8ce59e82e99293e5b08...000000 + /// // cbtxMerkleProof: 0x16adb7aeec2cf254db0bab0f4a5083fb0e0a3f...63a4f4 + /// // - dap: 225 + /// // block: 0x02000020170fad0b6b1ccbdc4401d7b1c8ee868c6977d6ce...1e7f8f + /// // final: 0x0400000092945abbd7b9f0d407fcccbf418e4fc20570040c...a9b240 + /// // cbtx: 0x01000000...cf6e8f930acb8f38b588d76cd8c3da3258d5a7...000000 + /// // cbtxMerkleProof: 0x25575bcaf3e11970ccf835e88d6f97bedd6b85...bfdf46 + /// } + /// } + /// + /// ``` + /// public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: UInt64? = 5, max_dap: UInt64? = 5, limit: UInt64? = 0) -> Future<[BtcProofTarget]> { return execAndConvert(in3: in3, method: "btc_proofTarget",params: RPCObject(target_dap), RPCObject(verified_dap),max_diff == nil ? RPCObject.none : RPCObject(max_diff!),max_dap == nil ? RPCObject.none : RPCObject(max_dap!),limit == nil ? RPCObject.none : RPCObject(limit!), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) } /// Returns the hash of the best (tip) block in the longest blockchain. /// - Returns: the hash of the best block + /// + /// **Example** + /// + /// ```swift + /// BtcAPI(in3).getbestblockhash() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 000000000000000000039cbb4e842de0de9651852122b117d7ae6d7ac4fc1df6 + /// } + /// } + /// + /// ``` + /// public func getbestblockhash() -> Future { return execAndConvert(in3: in3, method: "getbestblockhash", convertWith: toString ) } diff --git a/swift/Sources/In3/API/EthAPI.swift b/swift/Sources/In3/API/EthAPI.swift index b0604e4f2..7c45dc369 100644 --- a/swift/Sources/In3/API/EthAPI.swift +++ b/swift/Sources/In3/API/EthAPI.swift @@ -51,6 +51,14 @@ public class EthAPI { /// /// - Parameter data : data to hash /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try EthAPI(in3).keccak(data: "0x1234567890") + /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + /// ``` + /// public func keccak(data: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "keccak",params: RPCObject(data), convertWith: toString ) } @@ -63,6 +71,14 @@ public class EthAPI { /// /// - Parameter data : data to hash /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try EthAPI(in3).sha3(data: "0x1234567890") + /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + /// ``` + /// public func sha3(data: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "web3_sha3",params: RPCObject(data), convertWith: toString ) } @@ -73,6 +89,14 @@ public class EthAPI { /// /// - Parameter data : data to hash /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try EthAPI(in3).sha256(data: "0x1234567890") + /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + /// ``` + /// public func sha256(data: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "sha256",params: RPCObject(data), convertWith: toString ) } @@ -89,6 +113,14 @@ public class EthAPI { /// /// - Parameter seed : the seed. If given the result will be deterministic. /// - Returns: the 32byte random data + /// + /// **Example** + /// + /// ```swift + /// let result = try EthAPI(in3).createKey() + /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + /// ``` + /// public func createKey(seed: String? = nil) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_createKey",params:seed == nil ? RPCObject.none : RPCObject(seed!), convertWith: toString ) } @@ -106,6 +138,23 @@ public class EthAPI { /// - Parameter account : the account to sign with /// - Parameter message : the message to sign /// - Returns: the signature (65 bytes) for the given message. + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ + /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" + /// } + /// } + /// + /// ``` + /// public func sign(account: String, message: String) -> Future { return execAndConvert(in3: in3, method: "eth_sign",params: RPCObject(account), RPCObject(message), convertWith: toString ) } @@ -113,6 +162,23 @@ public class EthAPI { /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. /// - Parameter tx : transaction to sign /// - Returns: the raw signed transaction + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).signTransaction(tx: {"data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gas":"0x76c0","gasPrice":"0x9184e72a000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x9184e72a"}) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ + /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" + /// } + /// } + /// + /// ``` + /// public func signTransaction(tx: EthTransaction) -> Future { return execAndConvert(in3: in3, method: "eth_signTransaction",params: RPCObject(tx.toRPCDict()), convertWith: toString ) } @@ -125,30 +191,228 @@ public class EthAPI { /// With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. /// /// - Returns: the highest known blocknumber + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).blockNumber() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xb8a2a5" + /// } + /// } + /// + /// ``` + /// public func blockNumber() -> Future { return execAndConvert(in3: in3, method: "eth_blockNumber", convertWith: toUInt64 ) } - /// returns information about a block by block number. + /// returns the given Block by number with transactionHashes + /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. /// - /// See [eth_getBlockByNumber](https://eth.wiki/json-rpc/API#eth_getBlockByNumber) for spec. + /// **Example** /// + /// ```swift + /// EthAPI(in3).getBlockByNumber(blockNumber: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // author: "0x0000000000000000000000000000000000000000" + /// // difficulty: "0x2" + /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 + /// // gasLimit: "0x7a1200" + /// // gasUsed: "0x20e145" + /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" + /// // logsBloom: 0x000008000000000000...00400100000000080 + /// // miner: "0x0000000000000000000000000000000000000000" + /// // number: "0x449956" + /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" + /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" + /// // sealFields: + /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" + /// // - "0x880000000000000000" + /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + /// // size: "0x74b" + /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" + /// // timestamp: "0x605aec86" + /// // totalDifficulty: "0x6564de" + /// // transactions: + /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" + /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" + /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" + /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" + /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" + /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" + /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" + /// // uncles: [] + /// } + /// } + /// + /// ``` + /// + public func getBlockByNumber(blockNumber: UInt64) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) + } + + /// returns the given Block by number with full transaction data /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` - /// - Parameter fullTx : if true the full transactions are contained in the result. /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - public func getBlockByNumber(blockNumber: UInt64, fullTx: Bool) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(fullTx), convertWith: { try EthBlockdata($0,$1) } ) + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getBlockByNumberWithTx(blockNumber: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // author: "0x0000000000000000000000000000000000000000" + /// // difficulty: "0x2" + /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 + /// // gasLimit: "0x7a1200" + /// // gasUsed: "0x20e145" + /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" + /// // logsBloom: 0x000008000000000000...00400100000000080 + /// // miner: "0x0000000000000000000000000000000000000000" + /// // number: "0x449956" + /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" + /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" + /// // sealFields: + /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" + /// // - "0x880000000000000000" + /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + /// // size: "0x74b" + /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" + /// // timestamp: "0x605aec86" + /// // totalDifficulty: "0x6564de" + /// // transactions: + /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" + /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" + /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" + /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" + /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" + /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" + /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" + /// // uncles: [] + /// } + /// } + /// + /// ``` + /// + public func getBlockByNumberWithTx(blockNumber: UInt64) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) } - /// Returns information about a block by hash. + /// returns the given Block by hash with transactionHashes + /// - Parameter blockHash : the blockHash of the block + /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. /// - /// See [eth_getBlockByHash](https://eth.wiki/json-rpc/API#eth_getBlockByHash) for spec. + /// **Example** /// + /// ```swift + /// EthAPI(in3).getBlockByHash(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // author: "0x0000000000000000000000000000000000000000" + /// // difficulty: "0x2" + /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 + /// // gasLimit: "0x7a1200" + /// // gasUsed: "0x20e145" + /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" + /// // logsBloom: 0x000008000000000000...00400100000000080 + /// // miner: "0x0000000000000000000000000000000000000000" + /// // number: "0x449956" + /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" + /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" + /// // sealFields: + /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" + /// // - "0x880000000000000000" + /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + /// // size: "0x74b" + /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" + /// // timestamp: "0x605aec86" + /// // totalDifficulty: "0x6564de" + /// // transactions: + /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" + /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" + /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" + /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" + /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" + /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" + /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" + /// // uncles: [] + /// } + /// } + /// + /// ``` + /// + public func getBlockByHash(blockHash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) + } + + /// returns the given Block by hash with full transaction data /// - Parameter blockHash : the blockHash of the block - /// - Parameter fullTx : if true the full transactions are contained in the result. /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - public func getBlockByHash(blockHash: String, fullTx: Bool) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(fullTx), convertWith: { try EthBlockdata($0,$1) } ) + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getBlockByHashWithTx(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // author: "0x0000000000000000000000000000000000000000" + /// // difficulty: "0x2" + /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 + /// // gasLimit: "0x7a1200" + /// // gasUsed: "0x20e145" + /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" + /// // logsBloom: 0x000008000000000000...00400100000000080 + /// // miner: "0x0000000000000000000000000000000000000000" + /// // number: "0x449956" + /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" + /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" + /// // sealFields: + /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" + /// // - "0x880000000000000000" + /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + /// // size: "0x74b" + /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" + /// // timestamp: "0x605aec86" + /// // totalDifficulty: "0x6564de" + /// // transactions: + /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" + /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" + /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" + /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" + /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" + /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" + /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" + /// // uncles: [] + /// } + /// } + /// + /// ``` + /// + public func getBlockByHashWithTx(blockHash: String) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) } /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByHash). @@ -186,6 +450,37 @@ public class EthAPI { /// - Parameter blockHash : the blockhash containing the transaction. /// - Parameter index : the transactionIndex /// - Returns: the transactiondata or `null` if it does not exist + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getTransactionByBlockHashAndIndex(blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee", index: "0xd5") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" + /// // blockNumber: "0xb8a4a9" + /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" + /// // gas: "0xac6b" + /// // gasPrice: "0x1bf08eb000" + /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" + /// // input: 0x095ea7b300000000000000000000000...a7640000 + /// // nonce: "0xa" + /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" + /// // transactionIndex: "0xd5" + /// // value: "0x0" + /// // type: "0x0" + /// // v: "0x25" + /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" + /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" + /// } + /// } + /// + /// ``` + /// public func getTransactionByBlockHashAndIndex(blockHash: String, index: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex",params: RPCObject(blockHash), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) } @@ -197,6 +492,37 @@ public class EthAPI { /// - Parameter blockNumber : the block number containing the transaction. /// - Parameter index : the transactionIndex /// - Returns: the transactiondata or `null` if it does not exist + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getTransactionByBlockNumberAndIndex(blockNumber: "0xb8a4a9", index: "0xd5") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" + /// // blockNumber: "0xb8a4a9" + /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" + /// // gas: "0xac6b" + /// // gasPrice: "0x1bf08eb000" + /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" + /// // input: 0x095ea7b300000000000000000000000...a7640000 + /// // nonce: "0xa" + /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" + /// // transactionIndex: "0xd5" + /// // value: "0x0" + /// // type: "0x0" + /// // v: "0x25" + /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" + /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" + /// } + /// } + /// + /// ``` + /// public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex",params: RPCObject(blockNumber), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) } @@ -207,6 +533,37 @@ public class EthAPI { /// /// - Parameter txHash : the transactionHash of the transaction. /// - Returns: the transactiondata or `null` if it does not exist + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getTransactionByHash(txHash: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" + /// // blockNumber: "0xb8a4a9" + /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" + /// // gas: "0xac6b" + /// // gasPrice: "0x1bf08eb000" + /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" + /// // input: 0x095ea7b300000000000000000000000...a7640000 + /// // nonce: "0xa" + /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" + /// // transactionIndex: "0xd5" + /// // value: "0x0" + /// // type: "0x0" + /// // v: "0x25" + /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" + /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" + /// } + /// } + /// + /// ``` + /// public func getTransactionByHash(txHash: String) -> Future { return execAndConvert(in3: in3, method: "eth_getTransactionByHash",params: RPCObject(txHash), convertWith: { try EthTransactiondata($0,$1) } ) } @@ -221,6 +578,22 @@ public class EthAPI { /// - Parameter account : address of the account /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the balance + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b", block: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x20599832af6ec00" + /// } + /// } + /// + /// ``` + /// public func getBalance(account: String, block: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getBalance",params: RPCObject(account), RPCObject(block), convertWith: toString ) } @@ -229,6 +602,22 @@ public class EthAPI { /// - Parameter account : address of the account /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the nonce + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b", block: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x5" + /// } + /// } + /// + /// ``` + /// public func getTransactionCount(account: String, block: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getTransactionCount",params: RPCObject(account), RPCObject(block), convertWith: toString ) } @@ -237,6 +626,22 @@ public class EthAPI { /// - Parameter account : address of the account /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the code as hex + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", block: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 0x6080604052348...6c634300050a0040 + /// } + /// } + /// + /// ``` + /// public func getCode(account: String, block: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getCode",params: RPCObject(account), RPCObject(block), convertWith: toString ) } @@ -246,6 +651,22 @@ public class EthAPI { /// - Parameter key : key to look for /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the value of the storage slot. + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0", block: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x19" + /// } + /// } + /// + /// ``` + /// public func getStorageAt(account: String, key: String, block: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_getStorageAt",params: RPCObject(account), RPCObject(key), RPCObject(block), convertWith: toString ) } @@ -283,6 +704,22 @@ public class EthAPI { /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the abi-encoded result of the function. + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).call(tx: {"to":"0x2736D225f85740f42D17987100dc8d58e9e16252","data":"0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001"}, block: "latest") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 0x0000000000000000000000000... + /// } + /// } + /// + /// ``` + /// public func call(tx: EthTx, block: UInt64) -> Future { return execAndConvert(in3: in3, method: "eth_call",params: RPCObject(tx.toRPCDict()), RPCObject(block), convertWith: toString ) } @@ -290,6 +727,47 @@ public class EthAPI { /// The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). /// - Parameter txHash : the transactionHash /// - Returns: the TransactionReceipt or `null` if it does not exist. + /// + /// **Example** + /// + /// ```swift + /// EthAPI(in3).getTransactionReceipt(txHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" + /// // blockNumber: "0x8c1e39" + /// // contractAddress: null + /// // cumulativeGasUsed: "0x2466d" + /// // gasUsed: "0x2466d" + /// // logs: + /// // - address: "0x85ec283a3ed4b66df4da23656d4bf8a507383bca" + /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" + /// // blockNumber: "0x8c1e39" + /// // data: 0x00000000000... + /// // logIndex: "0x0" + /// // removed: false + /// // topics: + /// // - "0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8" + /// // - "0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6" + /// // - "0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000" + /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" + /// // transactionIndex: "0x0" + /// // transactionLogIndex: "0x0" + /// // type: mined + /// // logsBloom: 0x00000000000000000000200000... + /// // root: null + /// // status: "0x1" + /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" + /// // transactionIndex: "0x0" + /// } + /// } + /// + /// ``` + /// public func getTransactionReceipt(txHash: String) -> Future { return execAndConvertOptional(in3: in3, method: "eth_getTransactionReceipt",params: RPCObject(txHash), convertWith: { try EthTransactionReceipt($0,$1) } ) } @@ -343,6 +821,111 @@ public struct EthTransaction { } } +/// the blockdata, or in case the block with that number does not exist, `null` will be returned. +public struct EthBlockdataWithTxHashes { + /// the block number. `null` when its pending block. + public var number: UInt64 + + /// hash of the block. `null` when its pending block. + public var hash: String + + /// hash of the parent block. + public var parentHash: String + + /// hash of the generated proof-of-work. `null` when its pending block. + public var nonce: UInt64 + + /// SHA3 of the uncles Merkle root in the block. + public var sha3Uncles: String + + /// the bloom filter for the logs of the block. `null` when its pending block. + public var logsBloom: String + + /// the root of the transaction trie of the block. + public var transactionsRoot: String + + /// the root of the final state trie of the block. + public var stateRoot: String + + /// the root of the receipts trie of the block. + public var receiptsRoot: String + + /// the address of the beneficiary to whom the mining rewards were given. + public var miner: String + + /// integer of the difficulty for this block. + public var difficulty: UInt64 + + /// integer of the total difficulty of the chain until this block. + public var totalDifficulty: UInt64 + + /// the "extra data" field of this block. + public var extraData: String + + /// integer the size of this block in bytes. + public var size: UInt64 + + /// the maximum gas allowed in this block. + public var gasLimit: UInt64 + + /// the total used gas by all transactions in this block. + public var gasUsed: UInt64 + + /// the unix timestamp for when the block was collated. + public var timestamp: UInt64 + + /// Array of transaction hashes + public var transactions: [String] + + /// Array of uncle hashes. + public var uncles: [String] + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + number = try toUInt64(obj["number"],false)! + hash = try toString(obj["hash"],false)! + parentHash = try toString(obj["parentHash"],false)! + nonce = try toUInt64(obj["nonce"],false)! + sha3Uncles = try toString(obj["sha3Uncles"],false)! + logsBloom = try toString(obj["logsBloom"],false)! + transactionsRoot = try toString(obj["transactionsRoot"],false)! + stateRoot = try toString(obj["stateRoot"],false)! + receiptsRoot = try toString(obj["receiptsRoot"],false)! + miner = try toString(obj["miner"],false)! + difficulty = try toUInt64(obj["difficulty"],false)! + totalDifficulty = try toUInt64(obj["totalDifficulty"],false)! + extraData = try toString(obj["extraData"],false)! + size = try toUInt64(obj["size"],false)! + gasLimit = try toUInt64(obj["gasLimit"],false)! + gasUsed = try toUInt64(obj["gasUsed"],false)! + timestamp = try toUInt64(obj["timestamp"],false)! + transactions = try toArray(obj["transactions"])!.map({ try toString($0,false)! }) + uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["number"] = RPCObject(number) + obj["hash"] = RPCObject(hash) + obj["parentHash"] = RPCObject(parentHash) + obj["nonce"] = RPCObject(nonce) + obj["sha3Uncles"] = RPCObject(sha3Uncles) + obj["logsBloom"] = RPCObject(logsBloom) + obj["transactionsRoot"] = RPCObject(transactionsRoot) + obj["stateRoot"] = RPCObject(stateRoot) + obj["receiptsRoot"] = RPCObject(receiptsRoot) + obj["miner"] = RPCObject(miner) + obj["difficulty"] = RPCObject(difficulty) + obj["totalDifficulty"] = RPCObject(totalDifficulty) + obj["extraData"] = RPCObject(extraData) + obj["size"] = RPCObject(size) + obj["gasLimit"] = RPCObject(gasLimit) + obj["gasUsed"] = RPCObject(gasUsed) + obj["timestamp"] = RPCObject(timestamp) + return obj + } +} + /// the blockdata, or in case the block with that number does not exist, `null` will be returned. public struct EthBlockdata { /// the block number. `null` when its pending block. diff --git a/swift/Sources/In3/API/In3API.swift b/swift/Sources/In3/API/In3API.swift index b211d0515..45c7f2dd6 100644 --- a/swift/Sources/In3/API/In3API.swift +++ b/swift/Sources/In3/API/In3API.swift @@ -20,6 +20,14 @@ public class In3API { /// - Parameter signature : the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. /// - Parameter params : a array of arguments. the number of arguments must match the arguments in the signature. /// - Returns: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) + /// // result = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" + /// ``` + /// public func abiEncode(signature: String, params: [AnyObject]) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_abiEncode",params: RPCObject(signature), RPCObject(params), convertWith: toString ) } @@ -28,6 +36,16 @@ public class In3API { /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. /// - Parameter data : the data to decode (usually the result of a eth_call) /// - Returns: a array with the values after decodeing. + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") + /// // result = + /// // - "0x1234567890123456789012345678901234567890" + /// // - "0x05" + /// ``` + /// public func abiDecode(signature: String, data: String) throws -> [RPCObject] { return try execLocalAndConvert(in3: in3, method: "in3_abiDecode",params: RPCObject(signature), RPCObject(data), convertWith: { try toArray($0,$1)! } ) } @@ -36,6 +54,14 @@ public class In3API { /// - Parameter address : the address to convert. /// - Parameter useChainId : if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) /// - Returns: the address-string using the upper/lowercase hex characters. + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) + /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" + /// ``` + /// public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress",params: RPCObject(address),useChainId == nil ? RPCObject.none : RPCObject(useChainId!), convertWith: toString ) } @@ -47,6 +73,22 @@ public class In3API { /// - Parameter name : the domain name UTS46 compliant string. /// - Parameter field : the required data, which could be one of ( `addr` - the address, `resolver` - the address of the resolver, `hash` - the namehash, `owner` - the owner of the domain) /// - Returns: the value of the specified field + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).ens(name: "cryptokitties.eth", field: "addr") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" + /// } + /// } + /// + /// ``` + /// public func ens(name: String, field: String? = "addr") -> Future { return execAndConvert(in3: in3, method: "in3_ens",params: RPCObject(name),field == nil ? RPCObject.none : RPCObject(field!), convertWith: toString ) } @@ -55,6 +97,14 @@ public class In3API { /// - Parameter value : the value, which may be floating number as string /// - Parameter unit : the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` /// - Returns: the value in wei as hex. + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).toWei(value: "20.0009123", unit: "eth") + /// // result = "0x01159183c4793db800" + /// ``` + /// public func toWei(value: String, unit: String? = "eth") throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_toWei",params: RPCObject(value),unit == nil ? RPCObject.none : RPCObject(unit!), convertWith: toString ) } @@ -64,6 +114,14 @@ public class In3API { /// - Parameter unit : the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` /// - Parameter digits : fix number of digits after the comma. If left out, only as many as needed will be included. /// - Returns: the value as string. + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) + /// // result = "0.158" + /// ``` + /// public func fromWei(value: String, unit: String, digits: UInt64? = nil) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_fromWei",params: RPCObject(value), RPCObject(unit),digits == nil ? RPCObject.none : RPCObject(digits!), convertWith: toString ) } @@ -71,6 +129,14 @@ public class In3API { /// extracts the address from a private key. /// - Parameter pk : the 32 bytes private key as hex. /// - Returns: the address + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// // result = "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" + /// ``` + /// public func pk2address(pk: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_pk2address",params: RPCObject(pk), convertWith: toString ) } @@ -78,6 +144,15 @@ public class In3API { /// extracts the public key from a private key. /// - Parameter pk : the 32 bytes private key as hex. /// - Returns: the public key as 64 bytes + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// // result = "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f7818\ + /// // 6577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" + /// ``` + /// public func pk2public(pk: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_pk2public",params: RPCObject(pk), convertWith: toString ) } @@ -87,6 +162,17 @@ public class In3API { /// - Parameter sig : the 65 bytes signature as hex. /// - Parameter sigtype : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw` /// - Returns: the extracted public key and address + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") + /// // result = + /// // publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c\ + /// // 4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" + /// // address: "0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4" + /// ``` + /// public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> In3Ecrecover { return try execLocalAndConvert(in3: in3, method: "in3_ecrecover",params: RPCObject(msg), RPCObject(sig),sigtype == nil ? RPCObject.none : RPCObject(sigtype!), convertWith: { try In3Ecrecover($0,$1) } ) } @@ -94,6 +180,23 @@ public class In3API { /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). /// - Returns: the unsigned raw transaction as hex. + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).prepareTx(tx: {"to":"0x63f666a23cbd135a91187499b5cc51d589c302a0","value":"0x100000000","from":"0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f"}) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a0850100000000\ + /// // 80018080" + /// } + /// } + /// + /// ``` + /// public func prepareTx(tx: In3Transaction) -> Future { return execAndConvert(in3: in3, method: "in3_prepareTx",params: RPCObject(tx.toRPCDict()), convertWith: toString ) } @@ -102,6 +205,24 @@ public class In3API { /// - Parameter tx : the raw unsigned transactiondata /// - Parameter from : the account to sign /// - Returns: the raw transaction with signature. + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xf86980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a08501000000\ + /// // 008026a03c5b094078383f3da3f65773ab1314e89ee76bc41f827f2ef211b2d3449e4435a077755\ + /// // f8d9b32966e1ad8f6c0e8c9376a4387ed237bdbf2db6e6b94016407e276" + /// } + /// } + /// + /// ``` + /// public func signTx(tx: String, from: String) -> Future { return execAndConvert(in3: in3, method: "in3_signTx",params: RPCObject(tx), RPCObject(from), convertWith: toString ) } @@ -111,6 +232,29 @@ public class In3API { /// - Parameter account : the account to sign if the account is a bytes32 it will be used as private key /// - Parameter msgType : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data) /// - Returns: the signature + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // message: "0x0102030405060708090a0b0c0d0e0f" + /// // messageHash: "0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67" + /// // signature: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792\ + /// // 264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b" + /// // r: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579" + /// // s: "0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152" + /// // v: 27 + /// } + /// } + /// + /// ``` + /// public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { return execAndConvert(in3: in3, method: "in3_signData",params: RPCObject(msg), RPCObject(account),msgType == nil ? RPCObject.none : RPCObject(msgType!), convertWith: { try In3SignData($0,$1) } ) } @@ -119,12 +263,28 @@ public class In3API { /// - Parameter key : Keydata as object as defined in the keystorefile /// - Parameter passphrase : the password to decrypt it. /// - Returns: a raw private key (32 bytes) + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") + /// // result = "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" + /// ``` + /// public func decryptKey(key: String, passphrase: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_decryptKey",params: RPCObject(key), RPCObject(passphrase), convertWith: toString ) } /// clears the incubed cache (usually found in the .in3-folder) /// - Returns: true indicating the success + /// + /// **Example** + /// + /// ```swift + /// let result = try In3API(in3).cacheClear() + /// // result = true + /// ``` + /// public func cacheClear() throws -> String { return try execLocalAndConvert(in3: in3, method: "in3_cacheClear", convertWith: toString ) } @@ -134,6 +294,45 @@ public class In3API { /// - Parameter seed : this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. /// - Parameter addresses : a optional array of addresses of signers the nodeList must include. /// - Returns: the current nodelist + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).nodeList(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // totalServers: 5 + /// // contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + /// // registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + /// // lastBlockNumber: 8669495 + /// // nodes: + /// // - url: https://in3-v2.slock.it/mainnet/nd-3 + /// // address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" + /// // index: 2 + /// // deposit: "10000000000000000" + /// // props: 29 + /// // timeout: 3600 + /// // registerTime: 1570109570 + /// // weight: 2000 + /// // proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" + /// // - url: https://in3-v2.slock.it/mainnet/nd-5 + /// // address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" + /// // index: 4 + /// // deposit: "10000000000000000" + /// // props: 29 + /// // timeout: 3600 + /// // registerTime: 1570109690 + /// // weight: 2000 + /// // proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" + /// } + /// } + /// + /// ``` + /// public func nodeList(limit: UInt64? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { return execAndConvert(in3: in3, method: "in3_nodeList",params:limit == nil ? RPCObject.none : RPCObject(limit!),seed == nil ? RPCObject.none : RPCObject(seed!),addresses == nil ? RPCObject.none : RPCObject(addresses!), convertWith: { try In3NodeList($0,$1) } ) } @@ -147,6 +346,28 @@ public class In3API { /// /// - Parameter blocks : array of requested blocks. /// - Returns: the Array with signatures of all the requires blocks. + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).sign(blocks: {"blockNumber":8770580}) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // - blockHash: "0xd8189793f64567992eaadefc51834f3d787b03e9a6850b8b9b8003d8d84a76c8" + /// // block: 8770580 + /// // r: "0x954ed45416e97387a55b2231bff5dd72e822e4a5d60fa43bc9f9e49402019337" + /// // s: "0x277163f586585092d146d0d6885095c35c02b360e4125730c52332cf6b99e596" + /// // v: 28 + /// // msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" + /// } + /// } + /// + /// ``` + /// public func sign(blocks: In3Blocks) -> Future { return execAndConvert(in3: in3, method: "in3_sign",params: RPCObject(blocks.toRPCDict()), convertWith: { try In3Sign($0,$1) } ) } @@ -154,6 +375,28 @@ public class In3API { /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. /// - Parameter address : address of whitelist contract /// - Returns: the whitelisted addresses + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // totalServers: 2 + /// // contract: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" + /// // lastBlockNumber: 1546354 + /// // nodes: + /// // - "0x1fe2e9bf29aa1938859af64c413361227d04059a" + /// // - "0x45d45e6ff99e6c34a235d263965910298985fcfe" + /// } + /// } + /// + /// ``` + /// public func whitelist(address: String) -> Future { return execAndConvert(in3: in3, method: "in3_whitelist",params: RPCObject(address), convertWith: { try In3Whitelist($0,$1) } ) } @@ -161,12 +404,46 @@ public class In3API { /// adds a raw private key as signer, which allows signing transactions. /// - Parameter pk : the 32byte long private key as hex string. /// - Returns: the address of given key. + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + /// } + /// } + /// + /// ``` + /// public func addRawKey(pk: String) -> Future { return execAndConvert(in3: in3, method: "in3_addRawKey",params: RPCObject(pk), convertWith: toString ) } /// returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. /// - Returns: the array of addresses of all registered signers. + /// + /// **Example** + /// + /// ```swift + /// In3API(in3).accounts() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + /// // - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" + /// } + /// } + /// + /// ``` + /// public func accounts() -> Future { return execAndConvert(in3: in3, method: "eth_accounts", convertWith: toString ) } diff --git a/swift/Sources/In3/API/IpfsAPI.swift b/swift/Sources/In3/API/IpfsAPI.swift index 0f5f1a4cb..10601775f 100644 --- a/swift/Sources/In3/API/IpfsAPI.swift +++ b/swift/Sources/In3/API/IpfsAPI.swift @@ -19,6 +19,22 @@ public class IpfsAPI { /// - Parameter ipfshash : the ipfs multi hash /// - Parameter encoding : the encoding used for the response. ( `hex` , `base64` or `utf8`) /// - Returns: the content matching the requested hash encoded in the defined encoding. + /// + /// **Example** + /// + /// ```swift + /// IpfsAPI(in3).get(ipfshash: "QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD", encoding: "utf8") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = I love Incubed + /// } + /// } + /// + /// ``` + /// public func get(ipfshash: String, encoding: String) -> Future { return execAndConvert(in3: in3, method: "ipfs_get",params: RPCObject(ipfshash), RPCObject(encoding), convertWith: toString ) } @@ -30,6 +46,22 @@ public class IpfsAPI { /// - Parameter data : the content encoded with the specified encoding. /// - Parameter encoding : the encoding used for the request. ( `hex` , `base64` or `utf8`) /// - Returns: the ipfs multi hash + /// + /// **Example** + /// + /// ```swift + /// IpfsAPI(in3).put(data: "I love Incubed", encoding: "utf8") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD + /// } + /// } + /// + /// ``` + /// public func put(data: String, encoding: String) -> Future { return execAndConvert(in3: in3, method: "ipfs_put",params: RPCObject(data), RPCObject(encoding), convertWith: toString ) } diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift index adf00a3fa..a5c84dd24 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -21,12 +21,66 @@ public class ZksyncAPI { /// returns the contract address /// - Returns: fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).contractAddress() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // govContract: "0x34460C0EB5074C29A9F6FE13b8e7E23A0D08aF01" + /// // mainContract: "0xaBEA9132b05A70803a4E85094fD0e1800777fBEF" + /// } + /// } + /// + /// ``` + /// public func contractAddress() -> Future { return execAndConvert(in3: in3, method: "zksync_contract_address", convertWith: { try ZksyncContractAddress($0,$1) } ) } /// returns the list of all available tokens /// - Returns: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).tokens() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // BAT: + /// // address: "0x0d8775f648430679a709e98d2b0cb6250d2887ef" + /// // decimals: 18 + /// // id: 8 + /// // symbol: BAT + /// // BUSD: + /// // address: "0x4fabb145d64652a948d72533023f6e7a623c7c53" + /// // decimals: 18 + /// // id: 6 + /// // symbol: BUSD + /// // DAI: + /// // address: "0x6b175474e89094c44da98b954eedeac495271d0f" + /// // decimals: 18 + /// // id: 1 + /// // symbol: DAI + /// // ETH: + /// // address: "0x0000000000000000000000000000000000000000" + /// // decimals: 18 + /// // id: 0 + /// // symbol: ETH + /// } + /// } + /// + /// ``` + /// public func tokens() -> Future<[String:ZksyncTokens]> { return execAndConvert(in3: in3, method: "zksync_tokens", convertWith: { try toObject($0,$1)!.mapValues({ try ZksyncTokens($0,false)! }) } ) } @@ -34,6 +88,34 @@ public class ZksyncAPI { /// returns account_info from the server /// - Parameter address : the account-address. if not specified, the client will try to use its own address based on the signer config. /// - Returns: the current state of the requested account. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).accountInfo() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // address: "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" + /// // committed: + /// // balances: {} + /// // nonce: 0 + /// // pubKeyHash: sync:0000000000000000000000000000000000000000 + /// // depositing: + /// // balances: {} + /// // id: null + /// // verified: + /// // balances: {} + /// // nonce: 0 + /// // pubKeyHash: sync:0000000000000000000000000000000000000000 + /// } + /// } + /// + /// ``` + /// public func accountInfo(address: String? = nil) -> Future { return execAndConvert(in3: in3, method: "zksync_account_info",params:address == nil ? RPCObject.none : RPCObject(address!), convertWith: { try ZksyncAccountInfo($0,$1) } ) } @@ -41,6 +123,26 @@ public class ZksyncAPI { /// returns the state or receipt of the the zksync-tx /// - Parameter tx : the txHash of the send tx /// - Returns: the current state of the requested tx. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).txInfo(tx: "sync-tx:e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // block: null + /// // executed: false + /// // failReason: null + /// // success: null + /// } + /// } + /// + /// ``` + /// public func txInfo(tx: String) -> Future { return execAndConvert(in3: in3, method: "zksync_tx_info",params: RPCObject(tx), convertWith: { try ZksyncTxInfo($0,$1) } ) } @@ -63,6 +165,22 @@ public class ZksyncAPI { /// /// - Parameter token : the token to pay the gas (either the symbol or the address) /// - Returns: the pubKeyHash, if it was executed successfully + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).setKey(token: "eth") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = sync:e41d2489571d322189246dafa5ebde1f4699f498 + /// } + /// } + /// + /// ``` + /// public func setKey(token: String) -> Future { return execAndConvert(in3: in3, method: "zksync_set_key",params: RPCObject(token), convertWith: toString ) } @@ -70,6 +188,14 @@ public class ZksyncAPI { /// returns the current PubKeyHash based on the configuration set. /// - Parameter pubKey : the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) /// - Returns: the pubKeyHash + /// + /// **Example** + /// + /// ```swift + /// let result = try ZksyncAPI(in3).pubkeyhash() + /// // result = sync:4dcd9bb4463121470c7232efb9ff23ec21398e58 + /// ``` + /// public func pubkeyhash(pubKey: String? = nil) throws -> String { return try execLocalAndConvert(in3: in3, method: "zksync_pubkeyhash",params:pubKey == nil ? RPCObject.none : RPCObject(pubKey!), convertWith: toString ) } @@ -79,12 +205,28 @@ public class ZksyncAPI { /// If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. /// /// - Returns: the pubKey + /// + /// **Example** + /// + /// ```swift + /// let result = try ZksyncAPI(in3).pubkey() + /// // result = "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc04" + /// ``` + /// public func pubkey() throws -> String { return try execLocalAndConvert(in3: in3, method: "zksync_pubkey", convertWith: toString ) } /// returns the address of the account used. /// - Returns: the account used. + /// + /// **Example** + /// + /// ```swift + /// let result = try ZksyncAPI(in3).accountAddress() + /// // result = "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" + /// ``` + /// public func accountAddress() throws -> String { return try execLocalAndConvert(in3: in3, method: "zksync_account_address", convertWith: toString ) } @@ -95,7 +237,29 @@ public class ZksyncAPI { /// when exchanging the data with other keys, all known data will be send using `zk_sign` as method, but instead of the raw message a object with those data will be passed. /// /// - Parameter message : the message to sign - /// - Returns: The return value are 96 bytes of signature: /// - `[0...32]` packed public key /// - `[32..64]` r-value /// - `[64..96]` s-value /// + /// - Returns: The return value are 96 bytes of signature: + /// - `[0...32]` packed public key + /// - `[32..64]` r-value + /// - `[64..96]` s-value + /// + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).sign(message: "0xaabbccddeeff") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c398\ + /// // 0e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31\ + /// // b69cd0910a432156a0977c3a5baa404547e01" + /// } + /// } + /// + /// ``` + /// public func sign(message: String) -> Future { return execAndConvert(in3: in3, method: "zksync_sign",params: RPCObject(message), convertWith: toString ) } @@ -107,6 +271,14 @@ public class ZksyncAPI { /// - Parameter message : the message which was supposed to be signed /// - Parameter signature : the signature (96 bytes) /// - Returns: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. + /// + /// **Example** + /// + /// ```swift + /// let result = try ZksyncAPI(in3).verify(message: "0xaabbccddeeff", signature: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01") + /// // result = 1 + /// ``` + /// public func verify(message: String, signature: String) throws -> UInt64 { return try execLocalAndConvert(in3: in3, method: "zksync_verify",params: RPCObject(message), RPCObject(signature), convertWith: toUInt64 ) } @@ -120,6 +292,22 @@ public class ZksyncAPI { /// returns current token-price /// - Parameter token : Symbol or address of the token /// - Returns: the token price + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).getTokenPrice(token: "WBTC") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 11320.002167 + /// } + /// } + /// + /// ``` + /// public func getTokenPrice(token: String) -> Future { return execAndConvert(in3: in3, method: "zksync_get_token_price",params: RPCObject(token), convertWith: toDouble ) } @@ -129,12 +317,50 @@ public class ZksyncAPI { /// - Parameter address : the address of the receipient /// - Parameter token : the symbol or address of the token to pay /// - Returns: the fees split up into single values + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).getTxFee(txType: "Transfer", address: "0xabea9132b05a70803a4e85094fd0e1800777fbef", token: "BAT") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // feeType: TransferToNew + /// // gasFee: "47684047990828528" + /// // gasPriceWei: "116000000000" + /// // gasTxAmount: "350" + /// // totalFee: "66000000000000000" + /// // zkpFee: "18378682992117666" + /// } + /// } + /// + /// ``` + /// public func getTxFee(txType: String, address: String, token: String) -> Future { return execAndConvert(in3: in3, method: "zksync_get_tx_fee",params: RPCObject(txType), RPCObject(address), RPCObject(token), convertWith: { try ZksyncTxFee($0,$1) } ) } /// returns private key used for signing zksync-transactions /// - Returns: the raw private key configured based on the signers seed + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).syncKey() .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x019125314fda133d5bf62cb454ee8c60927d55b68eae8b8b8bd13db814389cd6" + /// } + /// } + /// + /// ``` + /// public func syncKey() -> Future { return execAndConvert(in3: in3, method: "zksync_sync_key", convertWith: toString ) } @@ -145,6 +371,22 @@ public class ZksyncAPI { /// - Parameter approveDepositAmountForERC20 : if true and in case of an erc20-token, the client will send a approve transaction first, otherwise it is expected to be already approved. /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. /// - Returns: the opId. You can use `zksync_ethop_info` to follow the state-changes. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).deposit(amount: 1000, token: "WBTC") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = 74 + /// } + /// } + /// + /// ``` + /// public func deposit(amount: UInt64, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { return execAndConvert(in3: in3, method: "zksync_deposit",params: RPCObject(amount), RPCObject(token),approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject(approveDepositAmountForERC20!),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toUInt64 ) } @@ -155,6 +397,22 @@ public class ZksyncAPI { /// - Parameter token : the token as symbol or address /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).transfer(to: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1" + /// } + /// } + /// + /// ``` + /// public func transfer(to: String, amount: UInt64, token: String, account: String? = nil) -> Future { return execAndConvert(in3: in3, method: "zksync_transfer",params: RPCObject(to), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) } @@ -165,6 +423,22 @@ public class ZksyncAPI { /// - Parameter token : the token as symbol or address /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).withdraw(ethAddress: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1" + /// } + /// } + /// + /// ``` + /// public func withdraw(ethAddress: String, amount: UInt64, token: String, account: String? = nil) -> Future { return execAndConvert(in3: in3, method: "zksync_withdraw",params: RPCObject(ethAddress), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) } @@ -172,6 +446,47 @@ public class ZksyncAPI { /// withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. /// - Parameter token : the token as symbol or address /// - Returns: the transactionReceipt + /// + /// **Example** + /// + /// ```swift + /// ZksyncAPI(in3).emergencyWithdraw(token: "WBTC") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" + /// // blockNumber: "0x8c1e39" + /// // contractAddress: null + /// // cumulativeGasUsed: "0x2466d" + /// // gasUsed: "0x2466d" + /// // logs: + /// // - address: "0x85ec283a3ed4b66df4da23656d4bf8a507383bca" + /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" + /// // blockNumber: "0x8c1e39" + /// // data: 0x00000000000... + /// // logIndex: "0x0" + /// // removed: false + /// // topics: + /// // - "0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8" + /// // - "0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6" + /// // - "0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000" + /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" + /// // transactionIndex: "0x0" + /// // transactionLogIndex: "0x0" + /// // type: mined + /// // logsBloom: 0x00000000000000000000200000... + /// // root: null + /// // status: "0x1" + /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" + /// // transactionIndex: "0x0" + /// } + /// } + /// + /// ``` + /// public func emergencyWithdraw(token: String) -> Future { return execAndConvert(in3: in3, method: "zksync_emergency_withdraw",params: RPCObject(token), convertWith: { try ZksyncTransactionReceipt($0,$1) } ) } @@ -179,6 +494,14 @@ public class ZksyncAPI { /// calculate the public key based on multiple public keys signing together using schnorr musig signatures. /// - Parameter pubkeys : concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` /// - Returns: the compact public Key + /// + /// **Example** + /// + /// ```swift + /// let result = try ZksyncAPI(in3).aggregatePubkey(pubkeys: "0x0f61bfe164cc43b5a112bfbfb0583004e79dbfafc97a7daad14c5d511fea8e2435065ddd04329ec94be682bf004b03a5a4eeca9bf50a8b8b6023942adc0b3409") + /// // result = "0x9ce5b6f8db3fbbe66a3bdbd3b4731f19ec27f80ee03ead3c0708798dd949882b" + /// ``` + /// public func aggregatePubkey(pubkeys: String) throws -> String { return try execLocalAndConvert(in3: in3, method: "zksync_aggregate_pubkey",params: RPCObject(pubkeys), convertWith: toString ) } From 430d89039cef544a98b54990e0c90b9e8a71e7a2 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 14:51:58 +0200 Subject: [PATCH 109/221] support examples with complex structs --- c/src/verifier/eth1/basic/rpc.yml | 27 +++++++--- c/src/verifier/eth1/full/rpc.yml | 8 ++- scripts/generator/swift.js | 20 ++++++-- swift/Sources/In3/API/BtcAPI.swift | 4 +- swift/Sources/In3/API/EthAPI.swift | 72 +++++++++++++-------------- swift/Sources/In3/API/In3API.swift | 8 +-- swift/Sources/In3/API/ZksyncAPI.swift | 8 +-- 7 files changed, 87 insertions(+), 60 deletions(-) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 722c84278..9bb4b7ccf 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -190,22 +190,25 @@ eth: blockNumber: descr: the blockNumber or one of `latest`, `earliest`or `pending` type: uint + internalDefault : latest + optional: true fullTx: descr: if true the full transactions are contained in the result. + default: false type: bool result: optional: true options: - params: fullTx: false - name: getBlockByNumber - descr: returns the given Block by number with transactionHashes + name: getBlock + descr: returns the given Block by number with transactionHashes. if no blocknumber is specified the latest block will be returned. result: type: blockdataWithTxHashes - params: fullTx: false - name: getBlockByNumberWithTx - descr: returns the given Block by number with full transaction data + name: getBlockWithTx + descr: returns the given Block by number with full transaction data. if no blocknumber is specified the latest block will be returned. result: type: blockdata descr: the blockdata, or in case the block with that number does not exist, `null` will be returned. @@ -764,7 +767,9 @@ eth: descr: address of the account type: address block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or `latest` type: uint result: descr: the balance @@ -807,7 +812,9 @@ eth: descr: address of the account type: address block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or `latest` type: uint result: descr: the nonce @@ -851,7 +858,9 @@ eth: descr: address of the account type: address block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or `latest` type: uint result: descr: the code as hex @@ -897,7 +906,9 @@ eth: descr: key to look for type: bytes32 block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or`latest` type: uint result: descr: the value of the storage slot. diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml index 6d1a64025..c463a7380 100644 --- a/c/src/verifier/eth1/full/rpc.yml +++ b/c/src/verifier/eth1/full/rpc.yml @@ -7,7 +7,9 @@ eth: descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). type: transaction block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or `latest` type: uint | string result: @@ -51,7 +53,9 @@ eth: type: bytes optional: true block: - descr: the blockNumber or one of `latest`, `earliest`or `pending` + internalDefault : latest + optional: true + descr: the blockNumber or `latest` type: uint | string result: diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 79839f0ed..8c0c39fc1 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -8,7 +8,7 @@ const { link, toCmdParam } = require('./util') - +const isStruct = (c, typeConfigs) => typeof c.type == 'string' ? typeConfigs[c.type] : typeof c.type === 'object' configs = { In3Config: [ '/// The main Incubed Configuration', @@ -219,8 +219,8 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc params += (params ? '' : 'params:') + ( p.fixed === undefined ? (p.optional - ? name + ' == nil ? RPCObject.none : RPCObject(' + name + '!),' - : ' RPCObject(' + (converterName(type, false).startsWith('to') ? name : (name + '.toRPCDict()')) + '),') + ? name + ' == nil ? RPCObject' + (p.internalDefault ? ('(' + JSON.stringify(p.internalDefault) + ')') : '.none') + ' : RPCObject(' + (p.type === 'uint' ? ('String(format:"0x%1x",' + name + '!)') : name + '!') + '),' + : ' RPCObject(' + (converterName(type, false).startsWith('to') ? ((p.type === 'uint' ? ('String(format:"0x%1x",' + name + ')') : name)) : (name + '.toRPCDict()')) + '),') : (' RPCObject(' + JSON.stringify(p.fixed) + '), ') ) @@ -245,9 +245,21 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc if (r.descr) content.push(' /// - Returns: ' + rpc.result.descr.split('\n').join('\n /// ')) asArray(rpc.example).forEach(ex => { + function toSwiftValue(val, pIndex) { + const name = paramNames[pIndex] + const def = rpc.params[name] + if (!def) return JSON.stringify(val) + if (isStruct(def, types) && typeof val === 'object') { + let swiftType = getAPIType(def, types, structs, name, camelCaseUp(api_name)) + return swiftType + '(' + Object.keys(val).map(_ => _ + ': ' + JSON.stringify(val[_])).join(', ') + ')' + } + return JSON.stringify(val) + } const paramNames = Object.keys(rpc.params || {}) let x = '\n**Example**\n\n```swift\n' - let call = camelCaseUp(api_name) + 'API(in3).' + fnName + '(' + (ex.request || []).map((_, i) => paramNames[i] + ': ' + JSON.stringify(_)).join(', ') + ')' + let call = camelCaseUp(api_name) + 'API(in3).' + fnName + '(' + (ex.request || []) + .filter((_, i) => _ != rpc.params[paramNames[i]].internalDefault) + .map((_, i) => paramNames[i] + ': ' + toSwiftValue(_, i)).join(', ') + ')' if (rpc.sync) { x += 'let result = try ' + call + '\n' x += '// result = ' + (typeof ex.response === 'object' ? '\n// ' : '') + yaml.stringify(ex.response).trim().split('\n').join('\n// ') diff --git a/swift/Sources/In3/API/BtcAPI.swift b/swift/Sources/In3/API/BtcAPI.swift index b344bda45..8f343fe45 100644 --- a/swift/Sources/In3/API/BtcAPI.swift +++ b/swift/Sources/In3/API/BtcAPI.swift @@ -356,7 +356,7 @@ public class BtcAPI { /// ``` /// public func getdifficulty(blocknumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "getdifficulty",params: RPCObject(blocknumber), convertWith: toUInt64 ) + return execAndConvert(in3: in3, method: "getdifficulty",params: RPCObject(String(format:"0x%1x",blocknumber)), convertWith: toUInt64 ) } /// Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. @@ -408,7 +408,7 @@ public class BtcAPI { /// ``` /// public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: UInt64? = 5, max_dap: UInt64? = 5, limit: UInt64? = 0) -> Future<[BtcProofTarget]> { - return execAndConvert(in3: in3, method: "btc_proofTarget",params: RPCObject(target_dap), RPCObject(verified_dap),max_diff == nil ? RPCObject.none : RPCObject(max_diff!),max_dap == nil ? RPCObject.none : RPCObject(max_dap!),limit == nil ? RPCObject.none : RPCObject(limit!), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) + return execAndConvert(in3: in3, method: "btc_proofTarget",params: RPCObject(String(format:"0x%1x",target_dap)), RPCObject(String(format:"0x%1x",verified_dap)),max_diff == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",max_diff!)),max_dap == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",max_dap!)),limit == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",limit!)), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) } /// Returns the hash of the best (tip) block in the longest blockchain. diff --git a/swift/Sources/In3/API/EthAPI.swift b/swift/Sources/In3/API/EthAPI.swift index 7c45dc369..37df7bb1d 100644 --- a/swift/Sources/In3/API/EthAPI.swift +++ b/swift/Sources/In3/API/EthAPI.swift @@ -166,7 +166,7 @@ public class EthAPI { /// **Example** /// /// ```swift - /// EthAPI(in3).signTransaction(tx: {"data":"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gas":"0x76c0","gasPrice":"0x9184e72a000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x9184e72a"}) .observe(using: { + /// EthAPI(in3).signTransaction(tx: EthTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -211,14 +211,14 @@ public class EthAPI { return execAndConvert(in3: in3, method: "eth_blockNumber", convertWith: toUInt64 ) } - /// returns the given Block by number with transactionHashes + /// returns the given Block by number with transactionHashes. if no blocknumber is specified the latest block will be returned. /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. /// /// **Example** /// /// ```swift - /// EthAPI(in3).getBlockByNumber(blockNumber: "latest") .observe(using: { + /// EthAPI(in3).getBlock() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -258,18 +258,18 @@ public class EthAPI { /// /// ``` /// - public func getBlockByNumber(blockNumber: UInt64) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) + public func getBlock(blockNumber: UInt64? = nil) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params:blockNumber == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",blockNumber!)), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) } - /// returns the given Block by number with full transaction data + /// returns the given Block by number with full transaction data. if no blocknumber is specified the latest block will be returned. /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. /// /// **Example** /// /// ```swift - /// EthAPI(in3).getBlockByNumberWithTx(blockNumber: "latest") .observe(using: { + /// EthAPI(in3).getBlockWithTx() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -309,8 +309,8 @@ public class EthAPI { /// /// ``` /// - public func getBlockByNumberWithTx(blockNumber: UInt64) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params: RPCObject(blockNumber), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) + public func getBlockWithTx(blockNumber: UInt64? = nil) -> Future { + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params:blockNumber == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",blockNumber!)), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) } /// returns the given Block by hash with transactionHashes @@ -426,7 +426,7 @@ public class EthAPI { /// - Parameter blockNumber : the blockNumber of the block /// - Returns: the number of transactions in the block public func getBlockTransactionCountByNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber",params: RPCObject(blockNumber), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber",params: RPCObject(String(format:"0x%1x",blockNumber)), convertWith: toString ) } /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). @@ -440,7 +440,7 @@ public class EthAPI { /// - Parameter blockNumber : the blockNumber of the block /// - Returns: the number of uncles public func getUncleCountByBlockNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber",params: RPCObject(blockNumber), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber",params: RPCObject(String(format:"0x%1x",blockNumber)), convertWith: toString ) } /// returns the transaction data. @@ -482,7 +482,7 @@ public class EthAPI { /// ``` /// public func getTransactionByBlockHashAndIndex(blockHash: String, index: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex",params: RPCObject(blockHash), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex",params: RPCObject(blockHash), RPCObject(String(format:"0x%1x",index)), convertWith: { try EthTransactiondata($0,$1) } ) } /// returns the transaction data. @@ -524,7 +524,7 @@ public class EthAPI { /// ``` /// public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex",params: RPCObject(blockNumber), RPCObject(index), convertWith: { try EthTransactiondata($0,$1) } ) + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex",params: RPCObject(String(format:"0x%1x",blockNumber)), RPCObject(String(format:"0x%1x",index)), convertWith: { try EthTransactiondata($0,$1) } ) } /// returns the transaction data. @@ -576,13 +576,13 @@ public class EthAPI { /// gets the balance of an account for a given block /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or `latest` /// - Returns: the balance /// /// **Example** /// /// ```swift - /// EthAPI(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b", block: "latest") .observe(using: { + /// EthAPI(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -594,19 +594,19 @@ public class EthAPI { /// /// ``` /// - public func getBalance(account: String, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getBalance",params: RPCObject(account), RPCObject(block), convertWith: toString ) + public func getBalance(account: String, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_getBalance",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) } /// gets the nonce or number of transaction sent from this account at a given block /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or `latest` /// - Returns: the nonce /// /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b", block: "latest") .observe(using: { + /// EthAPI(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -618,19 +618,19 @@ public class EthAPI { /// /// ``` /// - public func getTransactionCount(account: String, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionCount",params: RPCObject(account), RPCObject(block), convertWith: toString ) + public func getTransactionCount(account: String, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionCount",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) } /// gets the code of a given contract /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or `latest` /// - Returns: the code as hex /// /// **Example** /// /// ```swift - /// EthAPI(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", block: "latest") .observe(using: { + /// EthAPI(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -642,20 +642,20 @@ public class EthAPI { /// /// ``` /// - public func getCode(account: String, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getCode",params: RPCObject(account), RPCObject(block), convertWith: toString ) + public func getCode(account: String, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_getCode",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) } /// gets the storage value of a given key /// - Parameter account : address of the account /// - Parameter key : key to look for - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or`latest` /// - Returns: the value of the storage slot. /// /// **Example** /// /// ```swift - /// EthAPI(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0", block: "latest") .observe(using: { + /// EthAPI(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -667,8 +667,8 @@ public class EthAPI { /// /// ``` /// - public func getStorageAt(account: String, key: String, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getStorageAt",params: RPCObject(account), RPCObject(key), RPCObject(block), convertWith: toString ) + public func getStorageAt(account: String, key: String, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_getStorageAt",params: RPCObject(account), RPCObject(key),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) } /// signs and sends a Transaction @@ -694,21 +694,21 @@ public class EthAPI { /// calculates the gas needed to execute a transaction. for spec see [eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimateGas) /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or `latest` /// - Returns: the amount of gass needed. - public func estimateGas(tx: EthTransaction, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_estimateGas",params: RPCObject(tx.toRPCDict()), RPCObject(block), convertWith: toString ) + public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_estimateGas",params: RPCObject(tx.toRPCDict()),block == nil ? RPCObject("latest") : RPCObject(block!), convertWith: toString ) } /// calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Parameter block : the blockNumber or one of `latest`, `earliest`or `pending` + /// - Parameter block : the blockNumber or `latest` /// - Returns: the abi-encoded result of the function. /// /// **Example** /// /// ```swift - /// EthAPI(in3).call(tx: {"to":"0x2736D225f85740f42D17987100dc8d58e9e16252","data":"0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001"}, block: "latest") .observe(using: { + /// EthAPI(in3).call(tx: EthTx(to: "0x2736D225f85740f42D17987100dc8d58e9e16252", data: "0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -720,8 +720,8 @@ public class EthAPI { /// /// ``` /// - public func call(tx: EthTx, block: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_call",params: RPCObject(tx.toRPCDict()), RPCObject(block), convertWith: toString ) + public func call(tx: EthTx, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_call",params: RPCObject(tx.toRPCDict()),block == nil ? RPCObject("latest") : RPCObject(block!), convertWith: toString ) } /// The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). diff --git a/swift/Sources/In3/API/In3API.swift b/swift/Sources/In3/API/In3API.swift index 45c7f2dd6..adfdd8419 100644 --- a/swift/Sources/In3/API/In3API.swift +++ b/swift/Sources/In3/API/In3API.swift @@ -123,7 +123,7 @@ public class In3API { /// ``` /// public func fromWei(value: String, unit: String, digits: UInt64? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_fromWei",params: RPCObject(value), RPCObject(unit),digits == nil ? RPCObject.none : RPCObject(digits!), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_fromWei",params: RPCObject(value), RPCObject(unit),digits == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",digits!)), convertWith: toString ) } /// extracts the address from a private key. @@ -184,7 +184,7 @@ public class In3API { /// **Example** /// /// ```swift - /// In3API(in3).prepareTx(tx: {"to":"0x63f666a23cbd135a91187499b5cc51d589c302a0","value":"0x100000000","from":"0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f"}) .observe(using: { + /// In3API(in3).prepareTx(tx: In3Transaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -334,7 +334,7 @@ public class In3API { /// ``` /// public func nodeList(limit: UInt64? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { - return execAndConvert(in3: in3, method: "in3_nodeList",params:limit == nil ? RPCObject.none : RPCObject(limit!),seed == nil ? RPCObject.none : RPCObject(seed!),addresses == nil ? RPCObject.none : RPCObject(addresses!), convertWith: { try In3NodeList($0,$1) } ) + return execAndConvert(in3: in3, method: "in3_nodeList",params:limit == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",limit!)),seed == nil ? RPCObject.none : RPCObject(seed!),addresses == nil ? RPCObject.none : RPCObject(addresses!), convertWith: { try In3NodeList($0,$1) } ) } /// requests a signed blockhash from the node. @@ -350,7 +350,7 @@ public class In3API { /// **Example** /// /// ```swift - /// In3API(in3).sign(blocks: {"blockNumber":8770580}) .observe(using: { + /// In3API(in3).sign(blocks: In3Blocks(blockNumber: 8770580)) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift index a5c84dd24..9f47a0590 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -286,7 +286,7 @@ public class ZksyncAPI { /// returns the state or receipt of the the PriorityOperation /// - Parameter opId : the opId of a layer-operstion (like depositing) public func ethopInfo(opId: UInt64) -> Future { - return execAndConvert(in3: in3, method: "zksync_ethop_info",params: RPCObject(opId), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_ethop_info",params: RPCObject(String(format:"0x%1x",opId)), convertWith: toString ) } /// returns current token-price @@ -388,7 +388,7 @@ public class ZksyncAPI { /// ``` /// public func deposit(amount: UInt64, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_deposit",params: RPCObject(amount), RPCObject(token),approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject(approveDepositAmountForERC20!),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toUInt64 ) + return execAndConvert(in3: in3, method: "zksync_deposit",params: RPCObject(String(format:"0x%1x",amount)), RPCObject(token),approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject(approveDepositAmountForERC20!),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toUInt64 ) } /// sends a zksync-transaction and returns data including the transactionHash. @@ -414,7 +414,7 @@ public class ZksyncAPI { /// ``` /// public func transfer(to: String, amount: UInt64, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_transfer",params: RPCObject(to), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_transfer",params: RPCObject(to), RPCObject(String(format:"0x%1x",amount)), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) } /// withdraws the amount to the given `ethAddress` for the given token. @@ -440,7 +440,7 @@ public class ZksyncAPI { /// ``` /// public func withdraw(ethAddress: String, amount: UInt64, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_withdraw",params: RPCObject(ethAddress), RPCObject(amount), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_withdraw",params: RPCObject(ethAddress), RPCObject(String(format:"0x%1x",amount)), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) } /// withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. From f2b9604af24edb1ed3c330cf2975ed3b3957aa1a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Apr 2021 23:55:00 +0200 Subject: [PATCH 110/221] added UInt256 --- c/include/in3.rs.h | 1 + c/src/third-party/tommath/CMakeLists.txt | 5 + scripts/build_includeh.sh | 1 + swift/Sources/In3/Utils/Convert.swift | 28 ++++++ swift/Sources/In3/Utils/UInt256.swift | 115 +++++++++++++++++++++++ swift/Tests/In3Tests/In3Tests.swift | 27 +++++- 6 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 swift/Sources/In3/Utils/UInt256.swift diff --git a/c/include/in3.rs.h b/c/include/in3.rs.h index 0eb4f5991..2dabd57d0 100644 --- a/c/include/in3.rs.h +++ b/c/include/in3.rs.h @@ -14,3 +14,4 @@ #include "in3/in3_init.h" #include "in3/log.h" #include "../src/tools/swift/swift.h" +#include "../src/third-party/tommath/tommath.h" diff --git a/c/src/third-party/tommath/CMakeLists.txt b/c/src/third-party/tommath/CMakeLists.txt index 04dbcd004..458cf3985 100644 --- a/c/src/third-party/tommath/CMakeLists.txt +++ b/c/src/third-party/tommath/CMakeLists.txt @@ -262,6 +262,11 @@ if (IN3API) set(SRC ${SRC} bn_mp_read_radix.c bn_mp_add_d.c bn_mp_sub_d.c bn_mp_radix_smap.c ) endif() +if (SWIFT) + ADD_DEFINITIONS(-DBN_MP_TORADIX_C -DBN_MP_RADIX_SIZE_C -DBN_MP_GET_DOUBLE_C -DBN_MP_GET_INT_C -DBN_MP_GET_LONG_LONG_C -DBN_MP_INIT_SET_C) + set(SRC ${SRC} bn_mp_toradix.c bn_mp_radix_size.c bn_mp_div_d.c bn_mp_get_double.c bn_mp_get_int.c bn_mp_get_long_long.c bn_mp_get_long.c bn_mp_init_set.c) +endif(SWIFT) + add_static_library( NAME tommath diff --git a/scripts/build_includeh.sh b/scripts/build_includeh.sh index 7437782e3..751a8fb59 100755 --- a/scripts/build_includeh.sh +++ b/scripts/build_includeh.sh @@ -48,4 +48,5 @@ cat <../c/include/in3.rs.h #include "in3/in3_init.h" #include "in3/log.h" #include "../src/tools/swift/swift.h" +#include "../src/third-party/tommath/tommath.h" EOF diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift index 897d67c46..3056bcab4 100644 --- a/swift/Sources/In3/Utils/Convert.swift +++ b/swift/Sources/In3/Utils/Convert.swift @@ -30,6 +30,34 @@ internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt return nil } + +/// converts a RPC-Object to UInt256 or throws +internal func toUInt256(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt256?{ + if let data = data { + switch data { + case let .integer(val): + return UInt256(val) + case let .string(val): + if let intVal = UInt256(val) { + return intVal + } else { + throw IncubedError.config(message: "Can not convert '\(val)' to uint256") + } + case .none: + if !optional { + throw IncubedError.config(message: "missing value") + } + return nil + default: + throw IncubedError.config(message: "Invalid type for Int") + } + } else if !optional { + throw IncubedError.config(message: "missing value") + } + return nil +} + + /// converts a RPC-Object to UInt64 or throws internal func toInt(_ data:RPCObject?, _ optional:Bool = true) throws -> Int?{ if let data = data { diff --git a/swift/Sources/In3/Utils/UInt256.swift b/swift/Sources/In3/Utils/UInt256.swift new file mode 100644 index 000000000..2bae3b9b5 --- /dev/null +++ b/swift/Sources/In3/Utils/UInt256.swift @@ -0,0 +1,115 @@ +import CIn3 +import Foundation + + +extension mp_int { + init() { + self = mp_int(used: 0, alloc: 0, sign: 0, dp: nil) + } +} +/// a bigint implementation based on tommath to represent big numbers +public class UInt256: CustomStringConvertible, Hashable, Comparable { + var value = mp_int() + + public init() { + mp_init_set(&self.value, 0) + } + + public init(_ v:UInt64) { + mp_init_set(&self.value, v) + } + + public required convenience init(integerLiteral value: IntegerLiteralType) { + self.init(UInt64(value)) + } + + public init(_ value: UInt256) { + mp_init_copy(&self.value, &value.value) + } + + public func hash(into hasher: inout Hasher) { + toString(radix: 16).hash(into: &hasher) + } + + public init?(_ val: String, radix: Int = 10) { + var r = radix + var v = val + assert(r >= 2 && r <= 36, "Only radix from 2 to 36 are supported") + + if (v.starts(with: "0x")) { + v = String(v.suffix(from: v.index(v.startIndex, offsetBy: 2))) + r = 16 + } + + if mp_read_radix(&self.value, v, Int32(r)) != 0 { + return nil + } + } + + deinit { + mp_clear(&self.value); + } + + public var doubleValue: Double { + return mp_get_double(&self.value) + } + + public var uintValue: UInt { + return mp_get_int(&self.value) + } + + public var uint64Value: UInt64 { + return mp_get_long_long(&self.value) + } + + public func toString(radix: Int = 10) -> String { + assert(radix >= 2 && radix <= 36, "invalid radix") + + var len = Int32() + mp_radix_size(&self.value, Int32(radix), &len) + + var buf = [Int8]( repeating: 0, count: Int(len+1)) + mp_toradix(&self.value, &buf, Int32(radix)) + return String(cString: buf).lowercased() + } + + public var description: String { + return toString(radix: 10) + } + + public func compare(other: UInt256) -> Int32 { + return mp_cmp(&self.value, &other.value) + } + + public func add(_ val:UInt256) -> UInt256 { + let res:UInt256 = UInt256() + mp_add(&self.value, &val.value, &res.value) + return res + } + + +} + +public func == (a: UInt256, b: UInt256) -> Bool { + return a.compare(other: b) == MP_EQ +} + +public func < (a: UInt256, b: UInt256) -> Bool { + return a.compare(other: b) == MP_LT +} + +public func > (a: UInt256, b: UInt256) -> Bool { + return a.compare(other: b) == MP_GT +} + +public func >= (a: UInt256, b: UInt256) -> Bool { + return a.compare(other: b) != MP_LT +} + +public func <= (a: UInt256, b: UInt256) -> Bool { + return a.compare(other: b) != MP_GT +} + +public func + (a: UInt256, b: UInt256) -> UInt256 { + return a.add(b) +} diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index 288e342c0..f3de4d099 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -3,6 +3,24 @@ import Foundation @testable import In3 final class In3Tests: XCTestCase { + + func testUInt256() throws { + let val: UInt256 = UInt256(65535) + XCTAssertEqual(val.description,"65535") + XCTAssertEqual(val.uint64Value,UInt64(65535)) + XCTAssertEqual(val.toString(radix: 16),"ffff") + let r = val + UInt256(1) + XCTAssertEqual(r.description,"65536") + if let v = UInt256("0xffff") { + XCTAssertEqual(v.description,"65535") + } + else { + XCTFail("Could not parse UINt256") + } + + + } + func testLocal() throws { let in3 = try In3(In3Config(chainId: "mainnet")) let hash = try in3.execLocal("keccak",RPCObject("simon")) @@ -45,14 +63,14 @@ final class In3Tests: XCTestCase { let expect = XCTestExpectation(description: "Should get a hash-value") // let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) let in3 = try In3(In3Config(chainId: "mainnet")) - - EthAPI(in3).getTransactionReceipt(txHash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0") .observe(using: { + let eth = EthAPI(in3) + eth.getBlock().observe(using: { switch $0 { case let .failure(err): print(err.localizedDescription) case let .success( val ): - if let tx = val { - print("txIndex : ",tx.transactionIndex) + if let b = val { + print("block : ",b.miner) } else { print("on tx found ") } @@ -65,6 +83,7 @@ final class In3Tests: XCTestCase { static var allTests = [ + ("UInt256", testUInt256), ("execlocal", testLocal), ("execJSON", testJSON), ("exec", testExec), From 91ffe5fc063aac7a75f273d6cf965ebba8fff5da Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 8 Apr 2021 20:08:00 +0200 Subject: [PATCH 111/221] generate API with better UInt-Types --- c/src/api/eth1/rpc.yml | 12 +- c/src/core/client/rpc.yml | 8 +- c/src/nodeselect/full/rpc.yml | 175 +++++++++++++------------- c/src/pay/zksync/rpc.yml | 40 +++--- c/src/verifier/btc/rpc.yml | 110 ++++++++-------- c/src/verifier/eth1/basic/rpc.yml | 145 ++++++++------------- c/src/verifier/eth1/full/rpc.yml | 36 +++--- c/src/verifier/eth1/nano/rpc.yml | 21 ++-- scripts/build_rpc_docu.js | 1 + scripts/generator/swift.js | 120 ++++++++++-------- scripts/generator/util.js | 13 +- swift/Sources/In3/API/BtcAPI.swift | 90 ++++++------- swift/Sources/In3/API/EthAPI.swift | 145 +++++++++++---------- swift/Sources/In3/API/In3API.swift | 50 ++++---- swift/Sources/In3/API/IpfsAPI.swift | 4 +- swift/Sources/In3/API/ZksyncAPI.swift | 79 ++++++------ swift/Sources/In3/Config.swift | 34 ++--- swift/Sources/In3/Utils/JsonRpc.swift | 5 + swift/Sources/In3/Utils/UInt256.swift | 132 +++++++++++++++++-- swift/Tests/In3Tests/In3Tests.swift | 16 +++ 20 files changed, 674 insertions(+), 562 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index e0708cd33..522366653 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -8,20 +8,20 @@ types: type: address value: descr: value in wei to send - type: uint + type: uint256 optional: true gas: descr: the gas to be send along - type: uint + type: uint64 optional: true default: 21000 gasPrice: descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint + type: uint64 optional: true nonce: descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint + type: uint64 optional: true data: descr: the data-section of the transaction @@ -147,14 +147,14 @@ in3: params: value: descr: the value in wei - type: bytes | uint + type: uint256 example: "0x234324abdef" unit: descr: the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` type: string digits: descr: fix number of digits after the comma. If left out, only as many as needed will be included. - type: uint + type: int optional: true result: descr: the value as string. diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index c847373fa..f7fea74a1 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -24,7 +24,7 @@ in3: cmd: c finality: - type: uint | string + type: int descr: the number in percent needed in order reach finality (% of signature of the validators). example: 50 optional: true @@ -39,7 +39,7 @@ in3: default: false maxAttempts: - type: uint + type: int descr: max number of attempts in case a response is rejected. example: 1 optional: true @@ -79,7 +79,7 @@ in3: timeout: descr: specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. - type: uint + type: uint64 optional: true example: 100000 default: 20000 @@ -98,7 +98,7 @@ in3: replaceLatestBlock: descr: if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. - type: uint + type: int optional: true example: 6 cmd: l diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index c4738c8ee..7434f454f 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -11,7 +11,7 @@ in3: signatureCount: descr: number of signatures requested in order to verify the blockhash. - type: uint + type: int optional: true example: 2 default: 1 @@ -34,19 +34,19 @@ in3: minDeposit: descr: min stake of the server. Only nodes owning at least this amount will be chosen. - type: uint + type: uint256 optional: true example: 10000000 nodeProps: descr: used to identify the capabilities of the node. - type: uint + type: hex optional: true - example: 0xffff + example: '0xffff' requestCount: descr: the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. - type: uint + type: int optional: true example: 3 default: 2 @@ -80,7 +80,8 @@ in3: whiteList: descr: manual whitelist. - type: address[] + type: address + array: true optional: true registryId: @@ -94,7 +95,7 @@ in3: avgBlockTime: descr: average block time (seconds) for this chain. - type: uint + type: int optional: true verifiedHashes: @@ -104,7 +105,7 @@ in3: type: block: descr: block number - type: uint + type: uint64 hash: descr: verified hash corresponding to block number. type: bytes32 @@ -122,7 +123,7 @@ in3: type: string props: descr: used to identify the capabilities of the node (defaults to 0xFFFF). - type: uint + type: hex # Verified RPCs in3_nodeList: @@ -130,7 +131,7 @@ in3: params: limit: descr: if the number is defined and >0 this method will return a partial nodeList limited to the given number. - type: uint + type: int optional: true seed: descr: this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. @@ -156,22 +157,22 @@ in3: type: address index: descr: the index within the nodeList of the contract - type: uint + type: uint64 deposit: descr: the stored deposit - type: uint + type: uint256 props: descr: the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - type: uint + type: hex timeout: descr: the time in seconds describing how long the deposit would be locked when trying to unregister a node. - type: uint + type: uint64 registerTime: descr: unix timestamp in seconds when the node has registered. - type: uint + type: uint64 weight: descr: the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. - type: uint + type: uint64 proofHash: descr: | a hash value containing the above values. @@ -187,10 +188,10 @@ in3: type: bytes32 lastBlockNumber: descr: the blockNumber of the last change of the list (usually the last event). - type: uint + type: uint64 totalServer: descr: the total numbers of nodes. - type: uint + type: uint64 proof: descr: | @@ -236,43 +237,44 @@ in3: type: bytes signatures: descr: a array of signatures from the signers (if requested) of the above block. - type: bytes[] + array: true + type: bytes accounts: descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. - type: - "": - descr: The Account of the data-contract. + key: accountAdr + type: + address: + descr: the address of the account + type: address + balance: + descr: current Balance + type: uint256 + codeHash: + descr: hash of the contract code + type: bytes32 + nonce: + descr: nonce of the account + type: uint256 + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + array: true + type: bytes + storageProof: + descr: Array of Proofs for all required storage values type: - address: - descr: the address of the account - type: address - balance: - descr: current Balance - type: uint - codeHash: - descr: hash of the contract code + key: + descr: the storage key (or hash) type: bytes32 - nonce: - descr: nonce of the account - type: uint - storageHash: - descr: MerkleRoot of the Storage Trie + value: + descr: the storage value type: bytes32 - accountProof: - descr: MerkleProof of this account-node - type: bytes[] - storageProof: - descr: Array of Proofs for all required storage values - type: - key: - descr: the storage key (or hash) - type: uint - value: - descr: the storage value - type: bytes32 - proof: - descr: the merkleProof of the value down to the storageHash as MerkleRoot - type: bytes[] + proof: + descr: the merkleProof of the value down to the storageHash as MerkleRoot + array: true + type: bytes example: request: - 2 @@ -336,9 +338,6 @@ in3: - "0xf843a0200e2d5276120...423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" value: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - - - in3_sign: descr: | requests a signed blockhash from the node. @@ -353,7 +352,7 @@ in3: type: blockNumber: descr: the blockNumber to sign - type: uint + type: uint64 hash: descr: the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. type: bytes32 @@ -367,7 +366,7 @@ in3: type: bytes32 block: descr: the blocknumber - type: uint + type: uint64 r: descr: r-value of the signature type: bytes32 @@ -405,16 +404,16 @@ in3: type: address lastWhiteList: descr: the blockNumber of the last change of the in3 white list event. - type: uint + type: uint64 contract: descr: whitelist contract address. type: address lastBlockNumber: descr: the blockNumber of the last change of the list (usually the last event). - type: uint + type: uint64 totalServer: descr: the total numbers of whitelist nodes. - type: uint + type: uint64 proof: descr: | @@ -434,40 +433,40 @@ in3: type: bytes[] accounts: descr: a Object with the addresses of the db-contract as key and Proof as value. The Data Structure of the Proof is exactly the same as the result of - [`eth_getProof`](https://eth.wiki/json-rpc/API#eth_getproof), but it must contain the above described keys. + key: the account Adress type: - "": - descr: The Account of the data-contract. + address: + descr: the address of the account + type: address + balance: + descr: current Balance + type: uint256 + codeHash: + descr: hash of the contract code + type: bytes32 + nonce: + descr: nonce of the account + type: uint256 + storageHash: + descr: MerkleRoot of the Storage Trie + type: bytes32 + accountProof: + descr: MerkleProof of this account-node + array: true + type: bytes + storageProof: + descr: Array of Proofs for all required storage values type: - address: - descr: the address of the account - type: address - balance: - descr: current Balance - type: uint - codeHash: - descr: hash of the contract code + key: + descr: the storage key (or hash) type: bytes32 - nonce: - descr: nonce of the account - type: uint - storageHash: - descr: MerkleRoot of the Storage Trie + value: + descr: the storage value type: bytes32 - accountProof: - descr: MerkleProof of this account-node - type: bytes[] - storageProof: - descr: Array of Proofs for all required storage values - type: - key: - descr: the storage key (or hash) - type: uint - value: - descr: the storage value - type: bytes32 - proof: - descr: the merkleProof of the value down to the storageHash as MerkleRoot - type: bytes[] + proof: + array: true + descr: the merkleProof of the value down to the storageHash as MerkleRoot + type: bytes example: request: diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 95848c1df..50c20d3ef 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -126,10 +126,10 @@ zksync: type: address decimals: descr: decimals to be used when formating it for human readable representation. - type: uint + type: int id: descr: id which will be used when encoding the token. - type: uint + type: uint64 symbol: descr: symbol for the token type: string @@ -176,10 +176,10 @@ zksync: balances: descr: the token-balance key: the token - type: uint + type: uint256 nonce: descr: the nonce or transaction count. - type: uint + type: uint64 pubKeyHash: descr: the pubKeyHash set for the requested account or `0x0000...` if not set yet. type: address @@ -189,20 +189,20 @@ zksync: balances: descr: the token-values. key: the token - type: uint + type: uint256 id: descr: the assigned id of the account, which will be used when encoding it into the rollup. - type: uint + type: uint64 verified: descr: the state after the rollup was verified in L1. type: balances: descr: the token-balances. key: the token - type: uint + type: uint256 nonce: descr: the nonce or transaction count. - type: uint + type: uint64 pubKeyHash: descr: the pubKeyHash set for the requested account or `0x0000...` if not set yet. type: address @@ -234,7 +234,7 @@ zksync: type: block: descr: the blockNumber containing the tx or `null` if still pending - type: uint + type: uint64 executed: descr: true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. type: bool @@ -369,7 +369,7 @@ zksync: type: bytes96 result: descr: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. - type: uint + type: int example: cmdParams: -x request: @@ -382,7 +382,7 @@ zksync: params: opId: descr: the opId of a layer-operstion (like depositing) - type: uint + type: uint64 zksync_get_token_price: descr: returns current token-price @@ -419,19 +419,19 @@ zksync: type: string gasFee: descr: the gas for the core-transaction - type: uint + type: uint64 gasPriceWei: descr: current gasPrice - type: uint + type: uint64 gasTxAmount: descr: gasTxAmount - type: uint + type: uint64 totalFee: descr: total of all fees needed to pay in order to execute the transaction - type: uint + type: uint64 zkpFee: descr: zkpFee - type: uint + type: uint64 example: cmdParams: -x request: @@ -459,7 +459,7 @@ zksync: params: amount: descr: the value to deposit in wei (or smallest token unit) - type: uint + type: uint256 token: descr: the token as symbol or address type: string @@ -473,7 +473,7 @@ zksync: optional: true result: descr: the opId. You can use `zksync_ethop_info` to follow the state-changes. - type: uint + type: uint64 example: cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c request: @@ -489,7 +489,7 @@ zksync: type: address amount: descr: the value to transfer in wei (or smallest token unit) - type: uint + type: uint256 token: descr: the token as symbol or address type: string @@ -516,7 +516,7 @@ zksync: type: address amount: descr: the value to transfer in wei (or smallest token unit) - type: uint + type: uint256 token: descr: the token as symbol or address type: string diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 3b2ca496c..9d8878fad 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -8,10 +8,10 @@ types: type: int height: descr: The block height or index - type: uint + type: uint64 version: descr: The block version - type: uint + type: int versionHex: descr: The block version formatted in hexadecimal type: hex @@ -20,25 +20,25 @@ types: type: bytes32 time: descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 mediantime: descr: The median block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 nonce: descr: The nonce - type: uint + type: uint64 bits: descr: The bits ( 4 bytes as hex) representing the target type: bytes4 difficulty: descr: The difficulty - type: uint + type: uint256 chainwork: descr: Expected number of hashes required to produce the current chain (in hex) - type: uint + type: hex nTx: descr: The number of transactions in the block. - type: uint + type: int previousblockhash: descr: The hash of the previous block type: bytes32 @@ -61,19 +61,19 @@ types: type: bytes32 size: descr: The serialized transaction size - type: uint + type: uint64 vsize: descr: The virtual transaction size (differs from size for witness transactions) - type: uint + type: uint64 weight: descr: The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) - type: uint + type: uint64 version: descr: The version - type: uint + type: int locktime: descr: The lock time - type: uint + type: uint64 vin: descr: array of json objects of incoming txs to be used array: true @@ -83,7 +83,7 @@ types: type: bytes32 vout: descr: the index of the transaction out to be used - type: uint + type: uint64 scriptSig: descr: the script type: @@ -95,7 +95,7 @@ types: type: string sequence: descr: The script sequence number - type: uint + type: uint64 txinwitness: array: true descr: hex-encoded witness data (if any) @@ -106,10 +106,10 @@ types: type: value: descr: The Value in BTC - type: uint + type: float n: descr: the index - type: uint + type: int scriptPubKey: descr: the script pubkey type: @@ -121,7 +121,7 @@ types: type: string reqSigs: descr: the required signatures - type: uint + type: int type: descr: The type, eg 'pubkeyhash' type: string @@ -137,10 +137,10 @@ types: type: int blocktime: descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 time: descr: Same as "blocktime" - type: uint + type: uint64 btcblockWithTx: hash: @@ -151,10 +151,10 @@ types: type: int height: descr: The block height or index - type: uint + type: uint64 version: descr: The block version - type: uint + type: int versionHex: descr: The block version formatted in hexadecimal type: hex @@ -163,25 +163,25 @@ types: type: bytes32 time: descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 mediantime: descr: The median block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 nonce: descr: The nonce - type: uint + type: uint64 bits: descr: The bits ( 4 bytes as hex) representing the target type: bytes4 difficulty: descr: The difficulty - type: uint + type: uint256 chainwork: descr: Expected number of hashes required to produce the current chain (in hex) - type: uint + type: hex nTx: descr: The number of transactions in the block. - type: uint + type: int tx: descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) array: true @@ -202,10 +202,10 @@ types: type: int height: descr: The block height or index - type: uint + type: uint256 version: descr: The block version - type: uint + type: int versionHex: descr: The block version formatted in hexadecimal type: hex @@ -214,25 +214,25 @@ types: type: bytes32 time: descr: The block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 mediantime: descr: The median block time in seconds since epoch (Jan 1 1970 GMT) - type: uint + type: uint64 nonce: descr: The nonce - type: uint + type: uint64 bits: descr: The bits ( 4 bytes as hex) representing the target type: bytes4 difficulty: descr: The difficulty - type: uint + type: uint256 chainwork: descr: Expected number of hashes required to produce the current chain (in hex) - type: uint + type: hex nTx: descr: The number of transactions in the block. - type: uint + type: int tx: descr: the array of transactions either as ids (verbose=1) or full transaction (verbose=2) array: true @@ -272,14 +272,14 @@ btc: type: maxDAP: descr: max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. - type: uint + type: int example: 10 default: 20 optional: true maxDiff: descr: max increase (in percent) of the difference between targets when accepting new targets. - type: uint + type: int example: 5 default: 10 optional: true @@ -357,7 +357,7 @@ btc: type: bytes height: descr: the height of the block (block number) - type: uint + type: uint64 example: @@ -406,7 +406,7 @@ btc: in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string @@ -499,7 +499,7 @@ btc: in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string @@ -631,13 +631,13 @@ btc: in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string result: descr: the current blockheight - type: uint + type: uint64 proof: descr: | Since we can't prove the finality of the latest block we consider the `current block count` - `amount of finality` (set in `in3.finality`-field) as the latest block. The number of this block will be returned. Setting `in3.finality`=`0` will return the actual current block count. @@ -673,12 +673,12 @@ btc: descr: Returns the proof-of-work difficulty as a multiple of the minimum difficulty. params: blocknumber: - type: uint + type: uint64 descr: 'Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`)' in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string @@ -687,7 +687,7 @@ btc: type: bool result: - type: uint + type: uint256 descr: | - `blocknumber` is a certain number: the difficulty of this block - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) @@ -728,7 +728,7 @@ btc: type: bytes height: descr: the height of the block (block number) - type: uint + type: uint64 example: in3Params: finality: 8 @@ -748,29 +748,29 @@ btc: params: target_dap: descr: the number of the difficulty adjustment period (dap) we are looking for - type: uint + type: uint64 verified_dap: descr: the number of the closest already verified dap - type: uint + type: uint64 max_diff: descr: the maximum target difference between 2 verified daps - type: uint + type: int default: 5 optional: true max_dap: descr: the maximum amount of daps between 2 verified daps - type: uint + type: int default: 5 optional: true limit: descr: the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory - type: uint + type: int default: 0 optional: true in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string @@ -798,7 +798,7 @@ btc: type: dap: descr: the difficulty adjustement period - type: uint + type: uint64 block: descr: the first blockheader type: bytes @@ -880,7 +880,7 @@ btc: in3Params: finality: descr: defines the amount of finality headers - type: uint + type: int verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) type: string diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 9bb4b7ccf..5b57350ce 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -1,8 +1,9 @@ types: - blockdataWithTxHashes: + + blockheader: number: descr: the block number. `null` when its pending block. - type: uint + type: uint64 hash: descr: hash of the block. `null` when its pending block. type: bytes32 @@ -11,7 +12,7 @@ types: type: bytes32 nonce: descr: hash of the generated proof-of-work. `null` when its pending block. - type: uint + type: uint256 sha3Uncles: descr: SHA3 of the uncles Merkle root in the block. type: bytes32 @@ -32,94 +33,43 @@ types: type: address difficulty: descr: integer of the difficulty for this block. - type: uint + type: uint256 totalDifficulty: descr: integer of the total difficulty of the chain until this block. - type: uint + type: uint256 extraData: descr: the "extra data" field of this block. type: bytes size: descr: integer the size of this block in bytes. - type: uint + type: uint64 gasLimit: descr: the maximum gas allowed in this block. - type: uint + type: uint64 gasUsed: descr: the total used gas by all transactions in this block. - type: uint + type: uint64 timestamp: descr: the unix timestamp for when the block was collated. - type: uint - transactions: - descr: Array of transaction hashes - array: true - type: bytes32 + type: uint64 uncles: descr: Array of uncle hashes. array: true type: bytes32 - blockdata: - number: - descr: the block number. `null` when its pending block. - type: uint - hash: - descr: hash of the block. `null` when its pending block. - type: bytes32 - parentHash: - descr: hash of the parent block. - type: bytes32 - nonce: - descr: hash of the generated proof-of-work. `null` when its pending block. - type: uint - sha3Uncles: - descr: SHA3 of the uncles Merkle root in the block. - type: bytes32 - logsBloom: - descr: the bloom filter for the logs of the block. `null` when its pending block. - type: bytes256 - transactionsRoot: - descr: the root of the transaction trie of the block. - type: bytes32 - stateRoot: - descr: the root of the final state trie of the block. - type: bytes32 - receiptsRoot: - descr: the root of the receipts trie of the block. + blockdataWithTxHashes: + _extends: blockheader + transactions: + descr: Array of transaction hashes + array: true type: bytes32 - miner: - descr: the address of the beneficiary to whom the mining rewards were given. - type: address - difficulty: - descr: integer of the difficulty for this block. - type: uint - totalDifficulty: - descr: integer of the total difficulty of the chain until this block. - type: uint - extraData: - descr: the "extra data" field of this block. - type: bytes - size: - descr: integer the size of this block in bytes. - type: uint - gasLimit: - descr: the maximum gas allowed in this block. - type: uint - gasUsed: - descr: the total used gas by all transactions in this block. - type: uint - timestamp: - descr: the unix timestamp for when the block was collated. - type: uint + + blockdata: + _extends: blockheader transactions: descr: Array of transaction objects array: true type: transactiondata - uncles: - descr: Array of uncle hashes. - array: true - type: bytes32 transactiondata: to: @@ -130,22 +80,22 @@ types: type: address value: descr: value in wei to send - type: uint + type: uint256 gas: descr: the gas to be send along - type: uint + type: uint64 gasPrice: descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint + type: uint64 nonce: descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint + type: uint64 blockHash: descr: blockHash of the block holding this transaction or `null` if still pending. type: bytes32 blockNumber: descr: blockNumber of the block holding this transaction or `null` if still pending. - type: uint + type: uint64 hash: descr: transactionHash type: bytes32 @@ -154,7 +104,7 @@ types: type: bytes transactionIndex: descr: index of the transaaction in the block - type: uint + type: uint64 v: descr: recovery-byte of the signature type: byte @@ -177,7 +127,7 @@ eth: With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. result: descr: the highest known blocknumber - type: uint + type: uint64 example: response: "0xb8a2a5" @@ -189,7 +139,7 @@ eth: params: blockNumber: descr: the blockNumber or one of `latest`, `earliest`or `pending` - type: uint + type: uint64 internalDefault : latest optional: true fullTx: @@ -409,7 +359,7 @@ eth: params: blockNumber: descr: the blockNumber of the block - type: uint + type: uint64 proof: alias: eth_getUncleCountByBlockNumber result: @@ -431,7 +381,7 @@ eth: params: blockNumber: descr: the blockNumber of the block - type: uint + type: uint64 proof: descr: | Requests requiring proof for blocks will return a proof of type `blockProof`. Depending on the request, the proof will contain the following properties: @@ -456,7 +406,7 @@ eth: type: bytes32 index: descr: the transactionIndex - type: uint + type: int result: descr: the transactiondata or `null` if it does not exist type: transactiondata @@ -505,10 +455,10 @@ eth: params: blockNumber: descr: the block number containing the transaction. - type: uint + type: uint64 index: descr: the transactionIndex - type: uint + type: int result: descr: the transactiondata or `null` if it does not exist type: transactiondata @@ -718,7 +668,7 @@ eth: type: txIndex: descr: transactionIndex within the block - type: uint + type: int txProof: descr: the merkle Proof-Array for the transaction type: bytes[] @@ -737,12 +687,12 @@ eth: type: fromBlock: descr: Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - type: uint | string + type: uint64 optional: true default: latest toBlock: descr: Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - type: uint | string + type: uint64 optional: true default: latest address: @@ -768,9 +718,9 @@ eth: type: address block: internalDefault : latest - optional: true + optionalAPI: true descr: the blockNumber or `latest` - type: uint + type: uint64 result: descr: the balance proof: @@ -813,9 +763,9 @@ eth: type: address block: internalDefault : latest - optional: true + optionalAPI: true descr: the blockNumber or `latest` - type: uint + type: uint64 result: descr: the nonce proof: @@ -861,7 +811,7 @@ eth: internalDefault : latest optional: true descr: the blockNumber or `latest` - type: uint + type: uint64 result: descr: the code as hex proof: @@ -909,7 +859,7 @@ eth: internalDefault : latest optional: true descr: the blockNumber or`latest` - type: uint + type: uint64 result: descr: the value of the storage slot. proof: @@ -928,10 +878,10 @@ eth: type: address balance: descr: the balance - type: uint + type: uint256 nonce: descr: nonce of the account - type: uint + type: uint256 codeHash: descr: codehash of the account type: bytes32 @@ -946,20 +896,23 @@ eth: type: key: descr: the storage key (or hash) - type: uint + type: bytes32 value: descr: the storage value type: bytes32 proof: + array: true descr: the merkleProof of the value down to the storageHash as MerkleRoot - type: bytes[] + type: bytes signatures: descr: the array of signatures for all used blocks in the result. - type: signature[] + array: true + type: signature finalityBlocks: + array: true descr: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. - type: bytes[] + type: bytes descr: | Each of these account values are stored in the account-object: diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml index c463a7380..74ab557c5 100644 --- a/c/src/verifier/eth1/full/rpc.yml +++ b/c/src/verifier/eth1/full/rpc.yml @@ -8,9 +8,9 @@ eth: type: transaction block: internalDefault : latest - optional: true + optionalAPI: true descr: the blockNumber or `latest` - type: uint | string + type: uint64 result: descr: the amount of gass needed. @@ -33,20 +33,20 @@ eth: optional: true value: descr: value in wei to send - type: uint + type: uint256 optional: true gas: descr: the gas to be send along - type: uint + type: uint64 optional: true default: 21000 gasPrice: descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint + type: uint64 optional: true nonce: descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint + type: uint64 optional: true data: descr: the data-section of the transaction, which includes the functionhash and the abi-encoded arguments @@ -54,10 +54,9 @@ eth: optional: true block: internalDefault : latest - optional: true + optionalAPI: true descr: the blockNumber or `latest` - type: uint | string - + type: uint64 result: descr: the abi-encoded result of the function. @@ -123,10 +122,10 @@ eth: type: address balance: descr: the balance - type: uint + type: uint256 nonce: descr: nonce of the account - type: uint + type: uint64 codeHash: descr: codehash of the account type: bytes32 @@ -134,27 +133,32 @@ eth: descr: MerkleRoot of the Storage Trie type: bytes32 accountProof: + array: true descr: MerkleProof of this account-node - type: bytes[] + type: bytes storageProof: descr: Array of Proofs for all required storage values + array: true type: key: descr: the storage key (or hash) - type: uint + type: bytes32 value: descr: the storage value type: bytes32 proof: + array: true descr: the merkleProof of the value down to the storageHash as MerkleRoot - type: bytes[] + type: bytes signatures: + array: true descr: the array of signatures for all used blocks in the result. - type: signature[] + type: signature finalityBlocks: descr: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. - type: bytes[] + array: true + type: bytes descr: | Verifying the result of an `eth_call` is a little bit more complex because the response is a result of executing opcodes in the vm. The only way to do so is to reproduce it and execute the same code. That's why a call proof needs to provide all data used within the call. This means: diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml index eb8074a2e..e313f4e84 100644 --- a/c/src/verifier/eth1/nano/rpc.yml +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -2,7 +2,7 @@ types: transactionReceipt: blockNumber: descr: the blockNumber - type: uint + type: uint64 blockHash: descr: blockhash if ther containing block type: bytes32 @@ -11,10 +11,10 @@ types: type: address cumulativeGasUsed: descr: gas used for all transaction up to this one in the block - type: uint + type: uint64 gasUsed: descr: gas used by this transaction. - type: uint + type: uint64 logs: descr: array of events created during execution of the tx type: @@ -23,7 +23,7 @@ types: type: address blockNumber: descr: the blockNumber - type: uint + type: uint64 blockHash: descr: blockhash if ther containing block type: bytes32 @@ -32,22 +32,23 @@ types: type: bytes logIndex: descr: the index of the even within the block. - type: uint + type: int removed: descr: the reorg-status of the event. type: bool topics: + array: true descr: array of 32byte-topics of the indexed fields. - type: bytes32[] + type: bytes32 transactionHash: descr: requested transactionHash type: bytes32 transactionIndex: descr: transactionIndex within the containing block. - type: uint + type: int transactionLogIndex: descr: index of the event within the transaction. - type: uint + type: int type: descr: mining-status type: string @@ -56,13 +57,13 @@ types: type: bytes128 status: descr: error-status of the tx. 0x1 = success 0x0 = failure - type: uint + type: int transactionHash: descr: requested transactionHash type: bytes32 transactionIndex: descr: transactionIndex within the containing block. - type: uint + type: int eth: descr: | diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 0d6ea07c1..8b42bf564 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -26,6 +26,7 @@ let docs = {}, config = {}, types = {} function scan(dir) { for (const f of fs.readdirSync(dir, { withFileTypes: true })) { if (f.name == 'rpc.yml') { + console.error('parse ' + dir + '/' + f.name) const ob = yaml.parse(fs.readFileSync(dir + '/' + f.name, 'utf-8')) if (ob.types) { types = { ...types, ...ob.types } diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 8c0c39fc1..c2cdfd5ca 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -5,11 +5,10 @@ const { asArray, camelCaseLow, camelCaseUp, - link, - toCmdParam } = require('./util') + const isStruct = (c, typeConfigs) => typeof c.type == 'string' ? typeConfigs[c.type] : typeof c.type === 'object' -configs = { +const configs = { In3Config: [ '/// The main Incubed Configuration', 'public struct In3Config : Codable {', @@ -23,7 +22,7 @@ configs = { } function converterName(swiftType, asFn) { const type = swiftType.replace("String:", "").split(/[\[\]_\?\!]+/).join('') - if (type == 'UInt64' || type == 'Double' || type == 'Bool' || type == 'String' || type == 'Int' || type == 'AnyObject') return 'to' + type + if (type.startsWith("Int") || type.startsWith("UInt") || type == 'Double' || type == 'Bool' || type == 'String' || type == 'AnyObject') return 'to' + type if (swiftType.startsWith('[') && asFn) { if (swiftType.indexOf(':') >= 0) { if (swiftType.endsWith('?')) @@ -40,6 +39,8 @@ function converterName(swiftType, asFn) { } return asFn ? '{ try ' + type + '($0,$1) }' : type } + + function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api) { typesGenerated[swiftType] = 'placeholder' let content = ['/// ' + (descr || swiftType).split('\n').join('\n/// '), @@ -48,7 +49,7 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api let toRPC = '\n internal func toRPCDict() -> [String:RPCObject] {\n var obj:[String:RPCObject] = [:]' let init = ' internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws {' - init += '\n guard let obj = try toObject(rpc, optional) else { return nil }' + + '\n guard let obj = try toObject(rpc, optional) else { return nil }' for (let name of Object.keys(conf)) { @@ -80,7 +81,7 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api } else { init += '\n ' + name + ' = try ' + converterName(t, false) + '(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ')!' - if (converterName(t, false).startsWith('to')) + if (!isStruct(p, typeConfigs)) toRPC += '\n obj["' + name + '"] = ' + (p.optional ? (name + ' == nil ? RPCObject.none : RPCObject(' + name + '!)') : 'RPCObject(' + name + ')') } @@ -93,14 +94,15 @@ function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) let typedef = null if (typeof c.type === 'object') { - typedef = c.type + typedef = getType(c.type, typeConfigs) swiftType = camelCaseUp(api + camelCaseUp(c.typeName || prefix.startsWith('get') ? prefix.substr(3) : prefix)) } else if (typeConfigs[c.type]) { - typedef = typeConfigs[c.type] + typedef = getType(c.type, typeConfigs) swiftType = camelCaseUp((c.type.toLowerCase().startsWith(api.toLowerCase()) ? '' : api) + camelCaseUp(c.type)) } else if (swiftType == 'Uint') swiftType = 'UInt64' + else if (swiftType.startsWith('Uint')) swiftType = swiftType.replace('Uint', 'UInt') else if (swiftType == 'Float') swiftType = 'Double' else if (swiftType == 'Any') swiftType = 'AnyObject' else if (swiftType.startsWith('Byte') || swiftType == 'Address' || swiftType == 'Hex') swiftType = 'String' @@ -108,14 +110,12 @@ function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { swiftType = swiftType.substr(0, swiftType.length - 2) c = { ...c, array: true } } - if (typedef && !typesGenerated[swiftType]) { + if (typedef && typesGenerated && !typesGenerated[swiftType]) generateStruct(swiftType, typedef, c.descr, typeConfigs, typesGenerated, api); - } - if (c.array) swiftType = '[' + swiftType + ']' if (c.key) swiftType = '[String:' + swiftType + ']' - if (c.optional) swiftType += '?' + if (c.optional || c.optionalAPI) swiftType += '?' return swiftType } @@ -124,18 +124,12 @@ exports.updateConfig = function (pre, c, key) { const swift = configs[camelCaseUp(pre || 'In3Config')] const pad = pre ? ' ' : '' if (swift && key.indexOf('-') == -1 && key.indexOf('.') == -1) { - //console.error("NO Onbject for " + pre + ':Config' + camelCaseUp(pre || '')) - let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) - if (typeof c.type === 'object') { - swiftType = camelCaseUp(key) + let swiftType = getAPIType({ ...c, optional: false, array: false }, {}, {}, key, '') + if (typeof c.type === 'object') configs[swiftType] = [ ' /// ' + c.descr.replace(/\n/gm, '\n/// '), ' public struct ' + swiftType + ' : Codable {' ] - } - else if (swiftType == 'Uint') swiftType = 'UInt64' - else if (swiftType.startsWith('Byte') || swiftType.startsWith('Address')) swiftType = 'String' - if (swiftType.endsWith('[]')) swiftType = '[' + swiftType.substr(0, swiftType.length - 2) + ']' if (c.array) swiftType = '[' + swiftType + ']' swift.push('\n' + pad + ' /// ' + ( c.descr @@ -143,7 +137,7 @@ exports.updateConfig = function (pre, c, key) { + (c.enum ? ('\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n') : '') + (c.example ? ('\n\nExample: ' + (Array.isArray(c.example) ? '\n```\n' : '`') + asArray(c.example).map(ex => yaml.stringify(ex).trim()).join('\n') + (Array.isArray(c.example) ? '\n```' : '`')) : '') ).replace(/\n/gm, '\n' + pad + ' /// ')) - swift.push(pad + ' public var ' + key + ' : ' + swiftType + (c.optional || !pre ? '?' : '')) + swift.push(pad + ' public var ' + key + ' : ' + swiftType + ((c.optional || c.optionalAPI || !pre) ? '?' : '')) } } @@ -178,15 +172,45 @@ exports.generate_config = function () { ), { encoding: 'utf8' }) } +function toParam(name, p, types) { + if (p.fixed !== undefined) + return ' RPCObject(' + JSON.stringify(p.fixed) + ')' + + const optional = (p.optional || p.optionalAPI) ? '!' : '' + let expr = '' + if (isStruct(p, types)) + expr = name + optional + '.toRPCDict()' + else if (p.type == 'uint256') + expr = name + optional + else if (p.type.startsWith('uint') || p.type.startsWith('int')) + expr = 'String(format: "0x%1x", ' + name + optional + ')' + else + expr = name + optional + + if (p.optional || p.optionalAPI) { + return name + ' == nil' + + ' ? RPCObject' + (p.internalDefault ? ('(' + JSON.stringify(p.internalDefault) + ')') : '.none') + + ' : RPCObject( ' + expr + ' )' + } + else + return 'RPCObject( ' + expr + ')' +} + function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpcs) { - if (!rpc || rpc.skipApi) return - if (rpc.alias) + if (!rpc || rpc.skipApi) // ignore this rpc-function + return + if (rpc.alias) // create function from link but replace the name return createApiFunction(rpc_name, rpcs[rpc.alias], content, api_name, structs, types, rpcs) + + // we create a resulting typ with string as default. const r = { ...rpc.result, type: (rpc.result || {}).type || 'string' } + + // options means, we have different result types based on the input params if (r.options) { for (option of r.options) { let rr = { ...rpc, result: { ...r, ...option.result } } - if (option.example && rr.example) rr.example = { ...rr.example, response: option.example } + if (option.example && rr.example) + rr.example = { ...rr.example, response: option.example } if (option.params && rr.example && rr.example.request) rr.example = { ...rr.example, request: rr.example.request.slice(0, Object.keys(rpc.params).length - Object.keys(option.params).length) } rr.params = {} @@ -202,30 +226,29 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc return } - if (rpc.descr) content.push(' /// ' + rpc.descr.split('\n').join('\n /// ')) - else content.push(' /// ' + rpc_name) + // add description + content.push(' /// ' + (rpc.descr || rpc_name).split('\n').join('\n /// ')) + + // generate the function name const fnName = rpc.apiName || camelCaseLow(rpc_name.substr(rpc_name.indexOf('_') + 1)) + let s = ' public func ' + fnName + '(' let params = '' - if (rpc.params) { - for (let name of Object.keys(rpc.params)) { - let p = rpc.params[name] - let type = getAPIType(p, types, structs, name, camelCaseUp(api_name)) - if (p.fixed === undefined) { - if (!s.endsWith('(')) s += ', ' - content.push(' /// - Parameter ' + name + ' : ' + (p.descr || name).split('\n').join(' /// ')) - s += name + ': ' + type + (p.optional || p.default !== undefined ? ' = ' + (p.default !== undefined ? JSON.stringify(p.default) : 'nil') : '') - } - params += (params ? '' : 'params:') + ( - p.fixed === undefined - ? (p.optional - ? name + ' == nil ? RPCObject' + (p.internalDefault ? ('(' + JSON.stringify(p.internalDefault) + ')') : '.none') + ' : RPCObject(' + (p.type === 'uint' ? ('String(format:"0x%1x",' + name + '!)') : name + '!') + '),' - : ' RPCObject(' + (converterName(type, false).startsWith('to') ? ((p.type === 'uint' ? ('String(format:"0x%1x",' + name + ')') : name)) : (name + '.toRPCDict()')) + '),') - : (' RPCObject(' + JSON.stringify(p.fixed) + '), ') - ) + for (let name of Object.keys(rpc.params || {})) { + let p = rpc.params[name] + let type = getAPIType(p, types, structs, name, camelCaseUp(api_name)) + // add param as argument, (if not fixed) + if (p.fixed === undefined) { + if (!s.endsWith('(')) s += ', ' + content.push(' /// - Parameter ' + name + ' : ' + (p.descr || name).split('\n').join(' /// ')) + s += name + ': ' + type + (p.optional || p.default !== undefined ? ' = ' + (p.default !== undefined ? JSON.stringify(p.default) : 'nil') : '') } + // add the param to the rpc call + params += (params ? ' ' : ' params:') + toParam(name, p, types) + ',' } + + // handle return type const returnType = getAPIType(r, types, structs, fnName, camelCaseUp(api_name)) if (rpc.sync) { s += ') throws -> ' + returnType.replace("AnyObject", "RPCObject") + ' {' @@ -244,6 +267,7 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc } if (r.descr) content.push(' /// - Returns: ' + rpc.result.descr.split('\n').join('\n /// ')) + // add examples as comments asArray(rpc.example).forEach(ex => { function toSwiftValue(val, pIndex) { const name = paramNames[pIndex] @@ -300,19 +324,13 @@ exports.generateAPI = function (api_name, rpcs, descr, types) { ' }', '' ] + + // generate functions Object.keys(rpcs).forEach(rpc_name => createApiFunction(rpc_name, rpcs[rpc_name], content, api_name, structs, types, rpcs)) + // write the API to the filesystem fs.writeFileSync('../swift/Sources/In3/API/' + apiName + '.swift', ( content.join('\n') + '\n\n}\n' + Object.values(structs).join('\n\n') ), 'utf8') } - - - -function generate_swift_api(all) { - Object.keys(all).forEach(api_key => { - const api = all[api_key] - - }) -} diff --git a/scripts/generator/util.js b/scripts/generator/util.js index 783c408cb..4d5d7a7c1 100644 --- a/scripts/generator/util.js +++ b/scripts/generator/util.js @@ -11,7 +11,18 @@ exports.camelCaseLow = s => s ? s.substr(0, 1).toLowerCase() + camelCase(s).subs exports.asArray = val => val == undefined ? [] : (Array.isArray(val) ? val : [val]) exports.link = (name, label) => '[' + (label || name) + '](#' + name.toLowerCase().replace('_', '-') + ')' -exports.getType = (val, types) => typeof val === 'object' ? val : (types['' + val] || val) +exports.getType = (val, types) => { + if (typeof val === 'object') { + if (val._extends) { + const base = exports.getType(val._extends, types) + delete val._extends + Object.assign(val, { ...base, ...val }) + } + return val + } + if (!val) return undefined + return exports.getType(types['' + val], types) || val +} exports.toCmdParam = val => (typeof val == 'object' || Array.isArray(val) || ('' + val).indexOf(' ') >= 0) ? "'" + JSON.stringify(val) + "'" : ('' + val) exports.short_descr = function (d) { let zd = (d || '').trim() diff --git a/swift/Sources/In3/API/BtcAPI.swift b/swift/Sources/In3/API/BtcAPI.swift index 8f343fe45..e77c356f8 100644 --- a/swift/Sources/In3/API/BtcAPI.swift +++ b/swift/Sources/In3/API/BtcAPI.swift @@ -48,7 +48,7 @@ public class BtcAPI { /// ``` /// public func getblockheaderAsHex(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(0), convertWith: toString ) + return execAndConvertOptional(in3: in3, method: "getblockheader", params:RPCObject( hash), RPCObject(0), convertWith: toString ) } /// returns the blockheader @@ -89,7 +89,7 @@ public class BtcAPI { /// ``` /// public func getblockheader(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblockheader",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblockheader($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "getblockheader", params:RPCObject( hash), RPCObject(1), convertWith: { try Btcblockheader($0,$1) } ) } /// returns a hex representation of the block @@ -115,7 +115,7 @@ public class BtcAPI { /// ``` /// public func getBlockAsHex(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(0), convertWith: toString ) + return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(0), convertWith: toString ) } /// returns the block with transactionhashes @@ -160,7 +160,7 @@ public class BtcAPI { /// ``` /// public func getBlock(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(1), convertWith: { try Btcblock($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(1), convertWith: { try Btcblock($0,$1) } ) } /// returns the block with full transactions @@ -205,7 +205,7 @@ public class BtcAPI { /// ``` /// public func getBlockWithTx(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock",params: RPCObject(hash), RPCObject(2), convertWith: { try BtcblockWithTx($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(2), convertWith: { try BtcblockWithTx($0,$1) } ) } /// returns a hex representation of the tx @@ -231,7 +231,7 @@ public class BtcAPI { /// ``` /// public func getRawTransactionAsHex(txid: String, blockhash: String? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(0), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: toString ) + return execAndConvertOptional(in3: in3, method: "getrawtransaction", params:RPCObject( txid), RPCObject(0), blockhash == nil ? RPCObject.none : RPCObject( blockhash! ), convertWith: toString ) } /// returns the raw transaction @@ -309,7 +309,7 @@ public class BtcAPI { /// ``` /// public func getRawTransaction(txid: String, blockhash: String? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "getrawtransaction",params: RPCObject(txid), RPCObject(1), blockhash == nil ? RPCObject.none : RPCObject(blockhash!), convertWith: { try Btctransaction($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "getrawtransaction", params:RPCObject( txid), RPCObject(1), blockhash == nil ? RPCObject.none : RPCObject( blockhash! ), convertWith: { try Btctransaction($0,$1) } ) } /// Returns the number of blocks in the longest blockchain. @@ -355,8 +355,8 @@ public class BtcAPI { /// /// ``` /// - public func getdifficulty(blocknumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "getdifficulty",params: RPCObject(String(format:"0x%1x",blocknumber)), convertWith: toUInt64 ) + public func getdifficulty(blocknumber: UInt64) -> Future { + return execAndConvert(in3: in3, method: "getdifficulty", params:RPCObject( String(format: "0x%1x", blocknumber)), convertWith: toUInt256 ) } /// Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. @@ -407,8 +407,8 @@ public class BtcAPI { /// /// ``` /// - public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: UInt64? = 5, max_dap: UInt64? = 5, limit: UInt64? = 0) -> Future<[BtcProofTarget]> { - return execAndConvert(in3: in3, method: "btc_proofTarget",params: RPCObject(String(format:"0x%1x",target_dap)), RPCObject(String(format:"0x%1x",verified_dap)),max_diff == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",max_diff!)),max_dap == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",max_dap!)),limit == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",limit!)), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) + public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: Int? = 5, max_dap: Int? = 5, limit: Int? = 0) -> Future<[BtcProofTarget]> { + return execAndConvert(in3: in3, method: "btc_proofTarget", params:RPCObject( String(format: "0x%1x", target_dap)), RPCObject( String(format: "0x%1x", verified_dap)), max_diff == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", max_diff!) ), max_dap == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", max_dap!) ), limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) } /// Returns the hash of the best (tip) block in the longest blockchain. @@ -450,7 +450,7 @@ public struct Btcblockheader { public var height: UInt64 /// The block version - public var version: UInt64 + public var version: Int /// The block version formatted in hexadecimal public var versionHex: String @@ -471,13 +471,13 @@ public struct Btcblockheader { public var bits: String /// The difficulty - public var difficulty: UInt64 + public var difficulty: UInt256 /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: UInt64 + public var chainwork: String /// The number of transactions in the block. - public var nTx: UInt64 + public var nTx: Int /// The hash of the previous block public var previousblockhash: String @@ -490,16 +490,16 @@ public struct Btcblockheader { hash = try toString(obj["hash"],false)! confirmations = try toInt(obj["confirmations"],false)! height = try toUInt64(obj["height"],false)! - version = try toUInt64(obj["version"],false)! + version = try toInt(obj["version"],false)! versionHex = try toString(obj["versionHex"],false)! merkleroot = try toString(obj["merkleroot"],false)! time = try toUInt64(obj["time"],false)! mediantime = try toUInt64(obj["mediantime"],false)! nonce = try toUInt64(obj["nonce"],false)! bits = try toString(obj["bits"],false)! - difficulty = try toUInt64(obj["difficulty"],false)! - chainwork = try toUInt64(obj["chainwork"],false)! - nTx = try toUInt64(obj["nTx"],false)! + difficulty = try toUInt256(obj["difficulty"],false)! + chainwork = try toString(obj["chainwork"],false)! + nTx = try toInt(obj["nTx"],false)! previousblockhash = try toString(obj["previousblockhash"],false)! nextblockhash = try toString(obj["nextblockhash"],false)! } @@ -537,10 +537,10 @@ public struct Btcblock { public var confirmations: Int /// The block height or index - public var height: UInt64 + public var height: UInt256 /// The block version - public var version: UInt64 + public var version: Int /// The block version formatted in hexadecimal public var versionHex: String @@ -561,13 +561,13 @@ public struct Btcblock { public var bits: String /// The difficulty - public var difficulty: UInt64 + public var difficulty: UInt256 /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: UInt64 + public var chainwork: String /// The number of transactions in the block. - public var nTx: UInt64 + public var nTx: Int /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) public var tx: [String] @@ -582,17 +582,17 @@ public struct Btcblock { guard let obj = try toObject(rpc, optional) else { return nil } hash = try toString(obj["hash"],false)! confirmations = try toInt(obj["confirmations"],false)! - height = try toUInt64(obj["height"],false)! - version = try toUInt64(obj["version"],false)! + height = try toUInt256(obj["height"],false)! + version = try toInt(obj["version"],false)! versionHex = try toString(obj["versionHex"],false)! merkleroot = try toString(obj["merkleroot"],false)! time = try toUInt64(obj["time"],false)! mediantime = try toUInt64(obj["mediantime"],false)! nonce = try toUInt64(obj["nonce"],false)! bits = try toString(obj["bits"],false)! - difficulty = try toUInt64(obj["difficulty"],false)! - chainwork = try toUInt64(obj["chainwork"],false)! - nTx = try toUInt64(obj["nTx"],false)! + difficulty = try toUInt256(obj["difficulty"],false)! + chainwork = try toString(obj["chainwork"],false)! + nTx = try toInt(obj["nTx"],false)! tx = try toArray(obj["tx"])!.map({ try toString($0,false)! }) previousblockhash = try toString(obj["previousblockhash"],false)! nextblockhash = try toString(obj["nextblockhash"],false)! @@ -634,7 +634,7 @@ public struct BtcblockWithTx { public var height: UInt64 /// The block version - public var version: UInt64 + public var version: Int /// The block version formatted in hexadecimal public var versionHex: String @@ -655,13 +655,13 @@ public struct BtcblockWithTx { public var bits: String /// The difficulty - public var difficulty: UInt64 + public var difficulty: UInt256 /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: UInt64 + public var chainwork: String /// The number of transactions in the block. - public var nTx: UInt64 + public var nTx: Int /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) public var tx: [Btctransaction] @@ -677,16 +677,16 @@ public struct BtcblockWithTx { hash = try toString(obj["hash"],false)! confirmations = try toInt(obj["confirmations"],false)! height = try toUInt64(obj["height"],false)! - version = try toUInt64(obj["version"],false)! + version = try toInt(obj["version"],false)! versionHex = try toString(obj["versionHex"],false)! merkleroot = try toString(obj["merkleroot"],false)! time = try toUInt64(obj["time"],false)! mediantime = try toUInt64(obj["mediantime"],false)! nonce = try toUInt64(obj["nonce"],false)! bits = try toString(obj["bits"],false)! - difficulty = try toUInt64(obj["difficulty"],false)! - chainwork = try toUInt64(obj["chainwork"],false)! - nTx = try toUInt64(obj["nTx"],false)! + difficulty = try toUInt256(obj["difficulty"],false)! + chainwork = try toString(obj["chainwork"],false)! + nTx = try toInt(obj["nTx"],false)! tx = try toArray(obj["tx"])!.map({ try Btctransaction($0,false)! }) previousblockhash = try toString(obj["previousblockhash"],false)! nextblockhash = try toString(obj["nextblockhash"],false)! @@ -737,7 +737,7 @@ public struct Btctransaction { public var weight: UInt64 /// The version - public var version: UInt64 + public var version: Int /// The lock time public var locktime: UInt64 @@ -769,7 +769,7 @@ public struct Btctransaction { size = try toUInt64(obj["size"],false)! vsize = try toUInt64(obj["vsize"],false)! weight = try toUInt64(obj["weight"],false)! - version = try toUInt64(obj["version"],false)! + version = try toInt(obj["version"],false)! locktime = try toUInt64(obj["locktime"],false)! vin = try toArray(obj["vin"])!.map({ try BtcVin($0,false)! }) vout = try toArray(obj["vout"])!.map({ try BtcVout($0,false)! }) @@ -858,18 +858,18 @@ public struct BtcScriptSig { /// array of json objects describing the tx outputs public struct BtcVout { /// The Value in BTC - public var value: UInt64 + public var value: Double /// the index - public var n: UInt64 + public var n: Int /// the script pubkey public var scriptPubKey: BtcScriptPubKey internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - value = try toUInt64(obj["value"],false)! - n = try toUInt64(obj["n"],false)! + value = try toDouble(obj["value"],false)! + n = try toInt(obj["n"],false)! scriptPubKey = try BtcScriptPubKey(obj["scriptPubKey"],false)! } @@ -890,7 +890,7 @@ public struct BtcScriptPubKey { public var hex: String /// the required signatures - public var reqSigs: UInt64 + public var reqSigs: Int /// The type, eg 'pubkeyhash' public var type: String @@ -902,7 +902,7 @@ public struct BtcScriptPubKey { guard let obj = try toObject(rpc, optional) else { return nil } asm = try toString(obj["asm"],false)! hex = try toString(obj["hex"],false)! - reqSigs = try toUInt64(obj["reqSigs"],false)! + reqSigs = try toInt(obj["reqSigs"],false)! type = try toString(obj["type"],false)! addresses = try toArray(obj["addresses"])!.map({ try toString($0,false)! }) } diff --git a/swift/Sources/In3/API/EthAPI.swift b/swift/Sources/In3/API/EthAPI.swift index 37df7bb1d..231ca04f9 100644 --- a/swift/Sources/In3/API/EthAPI.swift +++ b/swift/Sources/In3/API/EthAPI.swift @@ -60,7 +60,7 @@ public class EthAPI { /// ``` /// public func keccak(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "keccak",params: RPCObject(data), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "keccak", params:RPCObject( data), convertWith: toString ) } /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. @@ -80,7 +80,7 @@ public class EthAPI { /// ``` /// public func sha3(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "web3_sha3",params: RPCObject(data), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "web3_sha3", params:RPCObject( data), convertWith: toString ) } /// Returns sha-256 of the given data. @@ -98,7 +98,7 @@ public class EthAPI { /// ``` /// public func sha256(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "sha256",params: RPCObject(data), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "sha256", params:RPCObject( data), convertWith: toString ) } /// the Network Version (currently 1) @@ -122,7 +122,7 @@ public class EthAPI { /// ``` /// public func createKey(seed: String? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_createKey",params:seed == nil ? RPCObject.none : RPCObject(seed!), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_createKey", params:seed == nil ? RPCObject.none : RPCObject( seed! ), convertWith: toString ) } /// The sign method calculates an Ethereum specific signature with: @@ -156,7 +156,7 @@ public class EthAPI { /// ``` /// public func sign(account: String, message: String) -> Future { - return execAndConvert(in3: in3, method: "eth_sign",params: RPCObject(account), RPCObject(message), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_sign", params:RPCObject( account), RPCObject( message), convertWith: toString ) } /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. @@ -180,7 +180,7 @@ public class EthAPI { /// ``` /// public func signTransaction(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_signTransaction",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_signTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) } /// returns the number of the most recent block. @@ -259,7 +259,7 @@ public class EthAPI { /// ``` /// public func getBlock(blockNumber: UInt64? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params:blockNumber == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",blockNumber!)), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber", params:blockNumber == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", blockNumber!) ), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) } /// returns the given Block by number with full transaction data. if no blocknumber is specified the latest block will be returned. @@ -310,7 +310,7 @@ public class EthAPI { /// ``` /// public func getBlockWithTx(blockNumber: UInt64? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber",params:blockNumber == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",blockNumber!)), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber", params:blockNumber == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", blockNumber!) ), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) } /// returns the given Block by hash with transactionHashes @@ -361,7 +361,7 @@ public class EthAPI { /// ``` /// public func getBlockByHash(blockHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash", params:RPCObject( blockHash), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) } /// returns the given Block by hash with full transaction data @@ -412,35 +412,35 @@ public class EthAPI { /// ``` /// public func getBlockByHashWithTx(blockHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash",params: RPCObject(blockHash), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash", params:RPCObject( blockHash), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) } /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByHash). /// - Parameter blockHash : the blockHash of the block /// - Returns: the number of transactions in the block public func getBlockTransactionCountByHash(blockHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByHash",params: RPCObject(blockHash), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByHash", params:RPCObject( blockHash), convertWith: toString ) } /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByNumber). /// - Parameter blockNumber : the blockNumber of the block /// - Returns: the number of transactions in the block public func getBlockTransactionCountByNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber",params: RPCObject(String(format:"0x%1x",blockNumber)), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber", params:RPCObject( String(format: "0x%1x", blockNumber)), convertWith: toString ) } /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). /// - Parameter blockHash : the blockHash of the block /// - Returns: the number of uncles public func getUncleCountByBlockHash(blockHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockHash",params: RPCObject(blockHash), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockHash", params:RPCObject( blockHash), convertWith: toString ) } /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockNumber). /// - Parameter blockNumber : the blockNumber of the block /// - Returns: the number of uncles public func getUncleCountByBlockNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber",params: RPCObject(String(format:"0x%1x",blockNumber)), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber", params:RPCObject( String(format: "0x%1x", blockNumber)), convertWith: toString ) } /// returns the transaction data. @@ -481,8 +481,8 @@ public class EthAPI { /// /// ``` /// - public func getTransactionByBlockHashAndIndex(blockHash: String, index: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex",params: RPCObject(blockHash), RPCObject(String(format:"0x%1x",index)), convertWith: { try EthTransactiondata($0,$1) } ) + public func getTransactionByBlockHashAndIndex(blockHash: String, index: Int) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex", params:RPCObject( blockHash), RPCObject( String(format: "0x%1x", index)), convertWith: { try EthTransactiondata($0,$1) } ) } /// returns the transaction data. @@ -523,8 +523,8 @@ public class EthAPI { /// /// ``` /// - public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex",params: RPCObject(String(format:"0x%1x",blockNumber)), RPCObject(String(format:"0x%1x",index)), convertWith: { try EthTransactiondata($0,$1) } ) + public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: Int) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex", params:RPCObject( String(format: "0x%1x", blockNumber)), RPCObject( String(format: "0x%1x", index)), convertWith: { try EthTransactiondata($0,$1) } ) } /// returns the transaction data. @@ -565,13 +565,13 @@ public class EthAPI { /// ``` /// public func getTransactionByHash(txHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByHash",params: RPCObject(txHash), convertWith: { try EthTransactiondata($0,$1) } ) + return execAndConvert(in3: in3, method: "eth_getTransactionByHash", params:RPCObject( txHash), convertWith: { try EthTransactiondata($0,$1) } ) } /// searches for events matching the given criteria. See [eth_getLogs](https://eth.wiki/json-rpc/API#eth_getLogs) for the spec. /// - Parameter filter : The filter criteria for the events. public func getLogs(filter: EthFilter) -> Future { - return execAndConvert(in3: in3, method: "eth_getLogs",params: RPCObject(filter.toRPCDict()), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getLogs", params:RPCObject( filter.toRPCDict()), convertWith: toString ) } /// gets the balance of an account for a given block @@ -594,8 +594,8 @@ public class EthAPI { /// /// ``` /// - public func getBalance(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getBalance",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) + public func getBalance(account: String, block: UInt64?) -> Future { + return execAndConvert(in3: in3, method: "eth_getBalance", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// gets the nonce or number of transaction sent from this account at a given block @@ -618,8 +618,8 @@ public class EthAPI { /// /// ``` /// - public func getTransactionCount(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionCount",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) + public func getTransactionCount(account: String, block: UInt64?) -> Future { + return execAndConvert(in3: in3, method: "eth_getTransactionCount", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// gets the code of a given contract @@ -643,7 +643,7 @@ public class EthAPI { /// ``` /// public func getCode(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getCode",params: RPCObject(account),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getCode", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// gets the storage value of a given key @@ -668,36 +668,36 @@ public class EthAPI { /// ``` /// public func getStorageAt(account: String, key: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getStorageAt",params: RPCObject(account), RPCObject(key),block == nil ? RPCObject("latest") : RPCObject(String(format:"0x%1x",block!)), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_getStorageAt", params:RPCObject( account), RPCObject( key), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// signs and sends a Transaction /// - Parameter tx : the transactiondata to send /// - Returns: the transactionHash public func sendTransaction(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_sendTransaction",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_sendTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) } /// signs and sends a Transaction, but then waits until the transaction receipt can be verified. Depending on the finality of the nodes, this may take a while, since only final blocks will be signed by the nodes. /// - Parameter tx : the transactiondata to send /// - Returns: the transactionReceipt public func sendTransactionAndWait(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_sendTransactionAndWait",params: RPCObject(tx.toRPCDict()), convertWith: { try EthTransactionReceipt($0,$1) } ) + return execAndConvert(in3: in3, method: "eth_sendTransactionAndWait", params:RPCObject( tx.toRPCDict()), convertWith: { try EthTransactionReceipt($0,$1) } ) } /// sends or broadcasts a prviously signed raw transaction. See [eth_sendRawTransaction](https://eth.wiki/json-rpc/API#eth_sendRawTransaction) /// - Parameter tx : the raw signed transactiondata to send /// - Returns: the transactionhash public func sendRawTransaction(tx: String) -> Future { - return execAndConvert(in3: in3, method: "eth_sendRawTransaction",params: RPCObject(tx), convertWith: toString ) + return execAndConvert(in3: in3, method: "eth_sendRawTransaction", params:RPCObject( tx), convertWith: toString ) } /// calculates the gas needed to execute a transaction. for spec see [eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimateGas) /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). /// - Parameter block : the blockNumber or `latest` /// - Returns: the amount of gass needed. - public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_estimateGas",params: RPCObject(tx.toRPCDict()),block == nil ? RPCObject("latest") : RPCObject(block!), convertWith: toString ) + public func estimateGas(tx: EthTransaction, block: UInt64?) -> Future { + return execAndConvert(in3: in3, method: "eth_estimateGas", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) @@ -720,8 +720,8 @@ public class EthAPI { /// /// ``` /// - public func call(tx: EthTx, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_call",params: RPCObject(tx.toRPCDict()),block == nil ? RPCObject("latest") : RPCObject(block!), convertWith: toString ) + public func call(tx: EthTx, block: UInt64?) -> Future { + return execAndConvert(in3: in3, method: "eth_call", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } /// The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). @@ -769,7 +769,7 @@ public class EthAPI { /// ``` /// public func getTransactionReceipt(txHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getTransactionReceipt",params: RPCObject(txHash), convertWith: { try EthTransactionReceipt($0,$1) } ) + return execAndConvertOptional(in3: in3, method: "eth_getTransactionReceipt", params:RPCObject( txHash), convertWith: { try EthTransactionReceipt($0,$1) } ) } @@ -783,7 +783,7 @@ public struct EthTransaction { public var from: String /// value in wei to send - public var value: UInt64? + public var value: UInt256? /// the gas to be send along public var gas: UInt64? @@ -801,7 +801,7 @@ public struct EthTransaction { guard let obj = try toObject(rpc, optional) else { return nil } to = try toString(obj["to"],false)! from = try toString(obj["from"],false)! - value = try toUInt64(obj["value"],true)! + value = try toUInt256(obj["value"],true)! gas = try toUInt64(obj["gas"],true)! gasPrice = try toUInt64(obj["gasPrice"],true)! nonce = try toUInt64(obj["nonce"],true)! @@ -823,6 +823,9 @@ public struct EthTransaction { /// the blockdata, or in case the block with that number does not exist, `null` will be returned. public struct EthBlockdataWithTxHashes { + /// Array of transaction hashes + public var transactions: [String] + /// the block number. `null` when its pending block. public var number: UInt64 @@ -833,7 +836,7 @@ public struct EthBlockdataWithTxHashes { public var parentHash: String /// hash of the generated proof-of-work. `null` when its pending block. - public var nonce: UInt64 + public var nonce: UInt256 /// SHA3 of the uncles Merkle root in the block. public var sha3Uncles: String @@ -854,10 +857,10 @@ public struct EthBlockdataWithTxHashes { public var miner: String /// integer of the difficulty for this block. - public var difficulty: UInt64 + public var difficulty: UInt256 /// integer of the total difficulty of the chain until this block. - public var totalDifficulty: UInt64 + public var totalDifficulty: UInt256 /// the "extra data" field of this block. public var extraData: String @@ -874,32 +877,29 @@ public struct EthBlockdataWithTxHashes { /// the unix timestamp for when the block was collated. public var timestamp: UInt64 - /// Array of transaction hashes - public var transactions: [String] - /// Array of uncle hashes. public var uncles: [String] internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } + transactions = try toArray(obj["transactions"])!.map({ try toString($0,false)! }) number = try toUInt64(obj["number"],false)! hash = try toString(obj["hash"],false)! parentHash = try toString(obj["parentHash"],false)! - nonce = try toUInt64(obj["nonce"],false)! + nonce = try toUInt256(obj["nonce"],false)! sha3Uncles = try toString(obj["sha3Uncles"],false)! logsBloom = try toString(obj["logsBloom"],false)! transactionsRoot = try toString(obj["transactionsRoot"],false)! stateRoot = try toString(obj["stateRoot"],false)! receiptsRoot = try toString(obj["receiptsRoot"],false)! miner = try toString(obj["miner"],false)! - difficulty = try toUInt64(obj["difficulty"],false)! - totalDifficulty = try toUInt64(obj["totalDifficulty"],false)! + difficulty = try toUInt256(obj["difficulty"],false)! + totalDifficulty = try toUInt256(obj["totalDifficulty"],false)! extraData = try toString(obj["extraData"],false)! size = try toUInt64(obj["size"],false)! gasLimit = try toUInt64(obj["gasLimit"],false)! gasUsed = try toUInt64(obj["gasUsed"],false)! timestamp = try toUInt64(obj["timestamp"],false)! - transactions = try toArray(obj["transactions"])!.map({ try toString($0,false)! }) uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) } @@ -928,6 +928,9 @@ public struct EthBlockdataWithTxHashes { /// the blockdata, or in case the block with that number does not exist, `null` will be returned. public struct EthBlockdata { + /// Array of transaction objects + public var transactions: [EthTransactiondata] + /// the block number. `null` when its pending block. public var number: UInt64 @@ -938,7 +941,7 @@ public struct EthBlockdata { public var parentHash: String /// hash of the generated proof-of-work. `null` when its pending block. - public var nonce: UInt64 + public var nonce: UInt256 /// SHA3 of the uncles Merkle root in the block. public var sha3Uncles: String @@ -959,10 +962,10 @@ public struct EthBlockdata { public var miner: String /// integer of the difficulty for this block. - public var difficulty: UInt64 + public var difficulty: UInt256 /// integer of the total difficulty of the chain until this block. - public var totalDifficulty: UInt64 + public var totalDifficulty: UInt256 /// the "extra data" field of this block. public var extraData: String @@ -979,32 +982,29 @@ public struct EthBlockdata { /// the unix timestamp for when the block was collated. public var timestamp: UInt64 - /// Array of transaction objects - public var transactions: [EthTransactiondata] - /// Array of uncle hashes. public var uncles: [String] internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } + transactions = try toArray(obj["transactions"])!.map({ try EthTransactiondata($0,false)! }) number = try toUInt64(obj["number"],false)! hash = try toString(obj["hash"],false)! parentHash = try toString(obj["parentHash"],false)! - nonce = try toUInt64(obj["nonce"],false)! + nonce = try toUInt256(obj["nonce"],false)! sha3Uncles = try toString(obj["sha3Uncles"],false)! logsBloom = try toString(obj["logsBloom"],false)! transactionsRoot = try toString(obj["transactionsRoot"],false)! stateRoot = try toString(obj["stateRoot"],false)! receiptsRoot = try toString(obj["receiptsRoot"],false)! miner = try toString(obj["miner"],false)! - difficulty = try toUInt64(obj["difficulty"],false)! - totalDifficulty = try toUInt64(obj["totalDifficulty"],false)! + difficulty = try toUInt256(obj["difficulty"],false)! + totalDifficulty = try toUInt256(obj["totalDifficulty"],false)! extraData = try toString(obj["extraData"],false)! size = try toUInt64(obj["size"],false)! gasLimit = try toUInt64(obj["gasLimit"],false)! gasUsed = try toUInt64(obj["gasUsed"],false)! timestamp = try toUInt64(obj["timestamp"],false)! - transactions = try toArray(obj["transactions"])!.map({ try EthTransactiondata($0,false)! }) uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) } @@ -1040,7 +1040,7 @@ public struct EthTransactiondata { public var from: String /// value in wei to send - public var value: UInt64 + public var value: UInt256 /// the gas to be send along public var gas: UInt64 @@ -1079,7 +1079,7 @@ public struct EthTransactiondata { guard let obj = try toObject(rpc, optional) else { return nil } to = try toString(obj["to"],false)! from = try toString(obj["from"],false)! - value = try toUInt64(obj["value"],false)! + value = try toUInt256(obj["value"],false)! gas = try toUInt64(obj["gas"],false)! gasPrice = try toUInt64(obj["gasPrice"],false)! nonce = try toUInt64(obj["nonce"],false)! @@ -1177,13 +1177,13 @@ public struct EthTransactionReceipt { public var logsBloom: String /// error-status of the tx. 0x1 = success 0x0 = failure - public var status: UInt64 + public var status: Int /// requested transactionHash public var transactionHash: String /// transactionIndex within the containing block. - public var transactionIndex: UInt64 + public var transactionIndex: Int internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } @@ -1194,9 +1194,9 @@ public struct EthTransactionReceipt { gasUsed = try toUInt64(obj["gasUsed"],false)! logs = try EthLogs(obj["logs"],false)! logsBloom = try toString(obj["logsBloom"],false)! - status = try toUInt64(obj["status"],false)! + status = try toInt(obj["status"],false)! transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toUInt64(obj["transactionIndex"],false)! + transactionIndex = try toInt(obj["transactionIndex"],false)! } internal func toRPCDict() -> [String:RPCObject] { @@ -1229,22 +1229,22 @@ public struct EthLogs { public var data: String /// the index of the even within the block. - public var logIndex: UInt64 + public var logIndex: Int /// the reorg-status of the event. public var removed: Bool /// array of 32byte-topics of the indexed fields. - public var topics: String + public var topics: [String] /// requested transactionHash public var transactionHash: String /// transactionIndex within the containing block. - public var transactionIndex: UInt64 + public var transactionIndex: Int /// index of the event within the transaction. - public var transactionLogIndex: UInt64 + public var transactionLogIndex: Int /// mining-status public var type: String @@ -1255,12 +1255,12 @@ public struct EthLogs { blockNumber = try toUInt64(obj["blockNumber"],false)! blockHash = try toString(obj["blockHash"],false)! data = try toString(obj["data"],false)! - logIndex = try toUInt64(obj["logIndex"],false)! + logIndex = try toInt(obj["logIndex"],false)! removed = try toBool(obj["removed"],false)! - topics = try toString(obj["topics"],false)! + topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toUInt64(obj["transactionIndex"],false)! - transactionLogIndex = try toUInt64(obj["transactionLogIndex"],false)! + transactionIndex = try toInt(obj["transactionIndex"],false)! + transactionLogIndex = try toInt(obj["transactionLogIndex"],false)! type = try toString(obj["type"],false)! } @@ -1272,7 +1272,6 @@ public struct EthLogs { obj["data"] = RPCObject(data) obj["logIndex"] = RPCObject(logIndex) obj["removed"] = RPCObject(removed) - obj["topics"] = RPCObject(topics) obj["transactionHash"] = RPCObject(transactionHash) obj["transactionIndex"] = RPCObject(transactionIndex) obj["transactionLogIndex"] = RPCObject(transactionLogIndex) @@ -1290,7 +1289,7 @@ public struct EthTx { public var from: String? /// value in wei to send - public var value: UInt64? + public var value: UInt256? /// the gas to be send along public var gas: UInt64? @@ -1308,7 +1307,7 @@ public struct EthTx { guard let obj = try toObject(rpc, optional) else { return nil } to = try toString(obj["to"],false)! from = try toString(obj["from"],true)! - value = try toUInt64(obj["value"],true)! + value = try toUInt256(obj["value"],true)! gas = try toUInt64(obj["gas"],true)! gasPrice = try toUInt64(obj["gasPrice"],true)! nonce = try toUInt64(obj["nonce"],true)! diff --git a/swift/Sources/In3/API/In3API.swift b/swift/Sources/In3/API/In3API.swift index adfdd8419..dbd3ca206 100644 --- a/swift/Sources/In3/API/In3API.swift +++ b/swift/Sources/In3/API/In3API.swift @@ -29,7 +29,7 @@ public class In3API { /// ``` /// public func abiEncode(signature: String, params: [AnyObject]) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_abiEncode",params: RPCObject(signature), RPCObject(params), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_abiEncode", params:RPCObject( signature), RPCObject( params), convertWith: toString ) } /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. @@ -47,7 +47,7 @@ public class In3API { /// ``` /// public func abiDecode(signature: String, data: String) throws -> [RPCObject] { - return try execLocalAndConvert(in3: in3, method: "in3_abiDecode",params: RPCObject(signature), RPCObject(data), convertWith: { try toArray($0,$1)! } ) + return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), convertWith: { try toArray($0,$1)! } ) } /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) @@ -63,7 +63,7 @@ public class In3API { /// ``` /// public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress",params: RPCObject(address),useChainId == nil ? RPCObject.none : RPCObject(useChainId!), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress", params:RPCObject( address), useChainId == nil ? RPCObject.none : RPCObject( useChainId! ), convertWith: toString ) } /// resolves a ens-name. @@ -90,7 +90,7 @@ public class In3API { /// ``` /// public func ens(name: String, field: String? = "addr") -> Future { - return execAndConvert(in3: in3, method: "in3_ens",params: RPCObject(name),field == nil ? RPCObject.none : RPCObject(field!), convertWith: toString ) + return execAndConvert(in3: in3, method: "in3_ens", params:RPCObject( name), field == nil ? RPCObject.none : RPCObject( field! ), convertWith: toString ) } /// converts the given value into wei. @@ -106,7 +106,7 @@ public class In3API { /// ``` /// public func toWei(value: String, unit: String? = "eth") throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_toWei",params: RPCObject(value),unit == nil ? RPCObject.none : RPCObject(unit!), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_toWei", params:RPCObject( value), unit == nil ? RPCObject.none : RPCObject( unit! ), convertWith: toString ) } /// converts a given uint (also as hex) with a wei-value into a specified unit. @@ -122,8 +122,8 @@ public class In3API { /// // result = "0.158" /// ``` /// - public func fromWei(value: String, unit: String, digits: UInt64? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_fromWei",params: RPCObject(value), RPCObject(unit),digits == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",digits!)), convertWith: toString ) + public func fromWei(value: UInt256, unit: String, digits: Int? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_fromWei", params:RPCObject( value), RPCObject( unit), digits == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", digits!) ), convertWith: toString ) } /// extracts the address from a private key. @@ -138,7 +138,7 @@ public class In3API { /// ``` /// public func pk2address(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2address",params: RPCObject(pk), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_pk2address", params:RPCObject( pk), convertWith: toString ) } /// extracts the public key from a private key. @@ -154,7 +154,7 @@ public class In3API { /// ``` /// public func pk2public(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2public",params: RPCObject(pk), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_pk2public", params:RPCObject( pk), convertWith: toString ) } /// extracts the public key and address from signature. @@ -174,7 +174,7 @@ public class In3API { /// ``` /// public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> In3Ecrecover { - return try execLocalAndConvert(in3: in3, method: "in3_ecrecover",params: RPCObject(msg), RPCObject(sig),sigtype == nil ? RPCObject.none : RPCObject(sigtype!), convertWith: { try In3Ecrecover($0,$1) } ) + return try execLocalAndConvert(in3: in3, method: "in3_ecrecover", params:RPCObject( msg), RPCObject( sig), sigtype == nil ? RPCObject.none : RPCObject( sigtype! ), convertWith: { try In3Ecrecover($0,$1) } ) } /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. @@ -198,7 +198,7 @@ public class In3API { /// ``` /// public func prepareTx(tx: In3Transaction) -> Future { - return execAndConvert(in3: in3, method: "in3_prepareTx",params: RPCObject(tx.toRPCDict()), convertWith: toString ) + return execAndConvert(in3: in3, method: "in3_prepareTx", params:RPCObject( tx.toRPCDict()), convertWith: toString ) } /// signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. @@ -224,7 +224,7 @@ public class In3API { /// ``` /// public func signTx(tx: String, from: String) -> Future { - return execAndConvert(in3: in3, method: "in3_signTx",params: RPCObject(tx), RPCObject(from), convertWith: toString ) + return execAndConvert(in3: in3, method: "in3_signTx", params:RPCObject( tx), RPCObject( from), convertWith: toString ) } /// signs the given data. @@ -256,7 +256,7 @@ public class In3API { /// ``` /// public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { - return execAndConvert(in3: in3, method: "in3_signData",params: RPCObject(msg), RPCObject(account),msgType == nil ? RPCObject.none : RPCObject(msgType!), convertWith: { try In3SignData($0,$1) } ) + return execAndConvert(in3: in3, method: "in3_signData", params:RPCObject( msg), RPCObject( account), msgType == nil ? RPCObject.none : RPCObject( msgType! ), convertWith: { try In3SignData($0,$1) } ) } /// decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. @@ -272,7 +272,7 @@ public class In3API { /// ``` /// public func decryptKey(key: String, passphrase: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_decryptKey",params: RPCObject(key), RPCObject(passphrase), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "in3_decryptKey", params:RPCObject( key), RPCObject( passphrase), convertWith: toString ) } /// clears the incubed cache (usually found in the .in3-folder) @@ -333,8 +333,8 @@ public class In3API { /// /// ``` /// - public func nodeList(limit: UInt64? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { - return execAndConvert(in3: in3, method: "in3_nodeList",params:limit == nil ? RPCObject.none : RPCObject(String(format:"0x%1x",limit!)),seed == nil ? RPCObject.none : RPCObject(seed!),addresses == nil ? RPCObject.none : RPCObject(addresses!), convertWith: { try In3NodeList($0,$1) } ) + public func nodeList(limit: Int? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { + return execAndConvert(in3: in3, method: "in3_nodeList", params:limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), seed == nil ? RPCObject.none : RPCObject( seed! ), addresses == nil ? RPCObject.none : RPCObject( addresses! ), convertWith: { try In3NodeList($0,$1) } ) } /// requests a signed blockhash from the node. @@ -369,7 +369,7 @@ public class In3API { /// ``` /// public func sign(blocks: In3Blocks) -> Future { - return execAndConvert(in3: in3, method: "in3_sign",params: RPCObject(blocks.toRPCDict()), convertWith: { try In3Sign($0,$1) } ) + return execAndConvert(in3: in3, method: "in3_sign", params:RPCObject( blocks.toRPCDict()), convertWith: { try In3Sign($0,$1) } ) } /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. @@ -398,7 +398,7 @@ public class In3API { /// ``` /// public func whitelist(address: String) -> Future { - return execAndConvert(in3: in3, method: "in3_whitelist",params: RPCObject(address), convertWith: { try In3Whitelist($0,$1) } ) + return execAndConvert(in3: in3, method: "in3_whitelist", params:RPCObject( address), convertWith: { try In3Whitelist($0,$1) } ) } /// adds a raw private key as signer, which allows signing transactions. @@ -421,7 +421,7 @@ public class In3API { /// ``` /// public func addRawKey(pk: String) -> Future { - return execAndConvert(in3: in3, method: "in3_addRawKey",params: RPCObject(pk), convertWith: toString ) + return execAndConvert(in3: in3, method: "in3_addRawKey", params:RPCObject( pk), convertWith: toString ) } /// returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. @@ -481,7 +481,7 @@ public struct In3Transaction { public var from: String /// value in wei to send - public var value: UInt64? + public var value: UInt256? /// the gas to be send along public var gas: UInt64? @@ -499,7 +499,7 @@ public struct In3Transaction { guard let obj = try toObject(rpc, optional) else { return nil } to = try toString(obj["to"],false)! from = try toString(obj["from"],false)! - value = try toUInt64(obj["value"],true)! + value = try toUInt256(obj["value"],true)! gas = try toUInt64(obj["gas"],true)! gasPrice = try toUInt64(obj["gasPrice"],true)! nonce = try toUInt64(obj["nonce"],true)! @@ -609,10 +609,10 @@ public struct In3Nodes { public var index: UInt64 /// the stored deposit - public var deposit: UInt64 + public var deposit: UInt256 /// the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - public var props: UInt64 + public var props: String /// the time in seconds describing how long the deposit would be locked when trying to unregister a node. public var timeout: UInt64 @@ -635,8 +635,8 @@ public struct In3Nodes { url = try toString(obj["url"],false)! address = try toString(obj["address"],false)! index = try toUInt64(obj["index"],false)! - deposit = try toUInt64(obj["deposit"],false)! - props = try toUInt64(obj["props"],false)! + deposit = try toUInt256(obj["deposit"],false)! + props = try toString(obj["props"],false)! timeout = try toUInt64(obj["timeout"],false)! registerTime = try toUInt64(obj["registerTime"],false)! weight = try toUInt64(obj["weight"],false)! diff --git a/swift/Sources/In3/API/IpfsAPI.swift b/swift/Sources/In3/API/IpfsAPI.swift index 10601775f..62d48fc2b 100644 --- a/swift/Sources/In3/API/IpfsAPI.swift +++ b/swift/Sources/In3/API/IpfsAPI.swift @@ -36,7 +36,7 @@ public class IpfsAPI { /// ``` /// public func get(ipfshash: String, encoding: String) -> Future { - return execAndConvert(in3: in3, method: "ipfs_get",params: RPCObject(ipfshash), RPCObject(encoding), convertWith: toString ) + return execAndConvert(in3: in3, method: "ipfs_get", params:RPCObject( ipfshash), RPCObject( encoding), convertWith: toString ) } /// Stores ipfs-content to the ipfs network. @@ -63,7 +63,7 @@ public class IpfsAPI { /// ``` /// public func put(data: String, encoding: String) -> Future { - return execAndConvert(in3: in3, method: "ipfs_put",params: RPCObject(data), RPCObject(encoding), convertWith: toString ) + return execAndConvert(in3: in3, method: "ipfs_put", params:RPCObject( data), RPCObject( encoding), convertWith: toString ) } diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/ZksyncAPI.swift index 9f47a0590..fb8740ace 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/ZksyncAPI.swift @@ -117,7 +117,7 @@ public class ZksyncAPI { /// ``` /// public func accountInfo(address: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_account_info",params:address == nil ? RPCObject.none : RPCObject(address!), convertWith: { try ZksyncAccountInfo($0,$1) } ) + return execAndConvert(in3: in3, method: "zksync_account_info", params:address == nil ? RPCObject.none : RPCObject( address! ), convertWith: { try ZksyncAccountInfo($0,$1) } ) } /// returns the state or receipt of the the zksync-tx @@ -144,7 +144,7 @@ public class ZksyncAPI { /// ``` /// public func txInfo(tx: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_tx_info",params: RPCObject(tx), convertWith: { try ZksyncTxInfo($0,$1) } ) + return execAndConvert(in3: in3, method: "zksync_tx_info", params:RPCObject( tx), convertWith: { try ZksyncTxInfo($0,$1) } ) } /// sets the signerkey based on the current pk or as configured in the config. @@ -182,7 +182,7 @@ public class ZksyncAPI { /// ``` /// public func setKey(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_set_key",params: RPCObject(token), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_set_key", params:RPCObject( token), convertWith: toString ) } /// returns the current PubKeyHash based on the configuration set. @@ -197,7 +197,7 @@ public class ZksyncAPI { /// ``` /// public func pubkeyhash(pubKey: String? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_pubkeyhash",params:pubKey == nil ? RPCObject.none : RPCObject(pubKey!), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "zksync_pubkeyhash", params:pubKey == nil ? RPCObject.none : RPCObject( pubKey! ), convertWith: toString ) } /// returns the current packed PubKey based on the config set. @@ -261,7 +261,7 @@ public class ZksyncAPI { /// ``` /// public func sign(message: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_sign",params: RPCObject(message), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_sign", params:RPCObject( message), convertWith: toString ) } /// returns 0 or 1 depending on the successfull verification of the signature. @@ -279,14 +279,14 @@ public class ZksyncAPI { /// // result = 1 /// ``` /// - public func verify(message: String, signature: String) throws -> UInt64 { - return try execLocalAndConvert(in3: in3, method: "zksync_verify",params: RPCObject(message), RPCObject(signature), convertWith: toUInt64 ) + public func verify(message: String, signature: String) throws -> Int { + return try execLocalAndConvert(in3: in3, method: "zksync_verify", params:RPCObject( message), RPCObject( signature), convertWith: toInt ) } /// returns the state or receipt of the the PriorityOperation /// - Parameter opId : the opId of a layer-operstion (like depositing) public func ethopInfo(opId: UInt64) -> Future { - return execAndConvert(in3: in3, method: "zksync_ethop_info",params: RPCObject(String(format:"0x%1x",opId)), convertWith: toString ) + return execAndConvert(in3: in3, method: "zksync_ethop_info", params:RPCObject( String(format: "0x%1x", opId)), convertWith: toString ) } /// returns current token-price @@ -309,7 +309,7 @@ public class ZksyncAPI { /// ``` /// public func getTokenPrice(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_get_token_price",params: RPCObject(token), convertWith: toDouble ) + return execAndConvert(in3: in3, method: "zksync_get_token_price", params:RPCObject( token), convertWith: toDouble ) } /// calculates the fees for a transaction. @@ -340,7 +340,7 @@ public class ZksyncAPI { /// ``` /// public func getTxFee(txType: String, address: String, token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_get_tx_fee",params: RPCObject(txType), RPCObject(address), RPCObject(token), convertWith: { try ZksyncTxFee($0,$1) } ) + return execAndConvert(in3: in3, method: "zksync_get_tx_fee", params:RPCObject( txType), RPCObject( address), RPCObject( token), convertWith: { try ZksyncTxFee($0,$1) } ) } /// returns private key used for signing zksync-transactions @@ -387,8 +387,8 @@ public class ZksyncAPI { /// /// ``` /// - public func deposit(amount: UInt64, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_deposit",params: RPCObject(String(format:"0x%1x",amount)), RPCObject(token),approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject(approveDepositAmountForERC20!),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toUInt64 ) + public func deposit(amount: UInt256, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_deposit", params:RPCObject( amount), RPCObject( token), approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject( approveDepositAmountForERC20! ), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toUInt64 ) } /// sends a zksync-transaction and returns data including the transactionHash. @@ -413,8 +413,8 @@ public class ZksyncAPI { /// /// ``` /// - public func transfer(to: String, amount: UInt64, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_transfer",params: RPCObject(to), RPCObject(String(format:"0x%1x",amount)), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + public func transfer(to: String, amount: UInt256, token: String, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_transfer", params:RPCObject( to), RPCObject( amount), RPCObject( token), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toString ) } /// withdraws the amount to the given `ethAddress` for the given token. @@ -439,8 +439,8 @@ public class ZksyncAPI { /// /// ``` /// - public func withdraw(ethAddress: String, amount: UInt64, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_withdraw",params: RPCObject(ethAddress), RPCObject(String(format:"0x%1x",amount)), RPCObject(token),account == nil ? RPCObject.none : RPCObject(account!), convertWith: toString ) + public func withdraw(ethAddress: String, amount: UInt256, token: String, account: String? = nil) -> Future { + return execAndConvert(in3: in3, method: "zksync_withdraw", params:RPCObject( ethAddress), RPCObject( amount), RPCObject( token), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toString ) } /// withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. @@ -488,7 +488,7 @@ public class ZksyncAPI { /// ``` /// public func emergencyWithdraw(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_emergency_withdraw",params: RPCObject(token), convertWith: { try ZksyncTransactionReceipt($0,$1) } ) + return execAndConvert(in3: in3, method: "zksync_emergency_withdraw", params:RPCObject( token), convertWith: { try ZksyncTransactionReceipt($0,$1) } ) } /// calculate the public key based on multiple public keys signing together using schnorr musig signatures. @@ -503,7 +503,7 @@ public class ZksyncAPI { /// ``` /// public func aggregatePubkey(pubkeys: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_aggregate_pubkey",params: RPCObject(pubkeys), convertWith: toString ) + return try execLocalAndConvert(in3: in3, method: "zksync_aggregate_pubkey", params:RPCObject( pubkeys), convertWith: toString ) } @@ -536,7 +536,7 @@ public struct ZksyncTokens { public var address: String /// decimals to be used when formating it for human readable representation. - public var decimals: UInt64 + public var decimals: Int /// id which will be used when encoding the token. public var id: UInt64 @@ -547,7 +547,7 @@ public struct ZksyncTokens { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } address = try toString(obj["address"],false)! - decimals = try toUInt64(obj["decimals"],false)! + decimals = try toInt(obj["decimals"],false)! id = try toUInt64(obj["id"],false)! symbol = try toString(obj["symbol"],false)! } @@ -599,7 +599,7 @@ public struct ZksyncAccountInfo { /// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. public struct ZksyncCommited { /// the token-balance - public var balances: [String:UInt64] + public var balances: [String:UInt256] /// the nonce or transaction count. public var nonce: UInt64 @@ -609,7 +609,7 @@ public struct ZksyncCommited { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) + balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) nonce = try toUInt64(obj["nonce"],false)! pubKeyHash = try toString(obj["pubKeyHash"],false)! } @@ -625,11 +625,11 @@ public struct ZksyncCommited { /// the state of all depositing-tx. public struct ZksyncDepositing { /// the token-values. - public var balances: [String:UInt64] + public var balances: [String:UInt256] internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) + balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) } } @@ -637,7 +637,7 @@ public struct ZksyncDepositing { /// the state after the rollup was verified in L1. public struct ZksyncVerified { /// the token-balances. - public var balances: [String:UInt64] + public var balances: [String:UInt256] /// the nonce or transaction count. public var nonce: UInt64 @@ -647,7 +647,7 @@ public struct ZksyncVerified { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt64($0,false)! }) + balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) nonce = try toUInt64(obj["nonce"],false)! pubKeyHash = try toString(obj["pubKeyHash"],false)! } @@ -758,13 +758,13 @@ public struct ZksyncTransactionReceipt { public var logsBloom: String /// error-status of the tx. 0x1 = success 0x0 = failure - public var status: UInt64 + public var status: Int /// requested transactionHash public var transactionHash: String /// transactionIndex within the containing block. - public var transactionIndex: UInt64 + public var transactionIndex: Int internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } @@ -775,9 +775,9 @@ public struct ZksyncTransactionReceipt { gasUsed = try toUInt64(obj["gasUsed"],false)! logs = try ZksyncLogs(obj["logs"],false)! logsBloom = try toString(obj["logsBloom"],false)! - status = try toUInt64(obj["status"],false)! + status = try toInt(obj["status"],false)! transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toUInt64(obj["transactionIndex"],false)! + transactionIndex = try toInt(obj["transactionIndex"],false)! } internal func toRPCDict() -> [String:RPCObject] { @@ -810,22 +810,22 @@ public struct ZksyncLogs { public var data: String /// the index of the even within the block. - public var logIndex: UInt64 + public var logIndex: Int /// the reorg-status of the event. public var removed: Bool /// array of 32byte-topics of the indexed fields. - public var topics: String + public var topics: [String] /// requested transactionHash public var transactionHash: String /// transactionIndex within the containing block. - public var transactionIndex: UInt64 + public var transactionIndex: Int /// index of the event within the transaction. - public var transactionLogIndex: UInt64 + public var transactionLogIndex: Int /// mining-status public var type: String @@ -836,12 +836,12 @@ public struct ZksyncLogs { blockNumber = try toUInt64(obj["blockNumber"],false)! blockHash = try toString(obj["blockHash"],false)! data = try toString(obj["data"],false)! - logIndex = try toUInt64(obj["logIndex"],false)! + logIndex = try toInt(obj["logIndex"],false)! removed = try toBool(obj["removed"],false)! - topics = try toString(obj["topics"],false)! + topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toUInt64(obj["transactionIndex"],false)! - transactionLogIndex = try toUInt64(obj["transactionLogIndex"],false)! + transactionIndex = try toInt(obj["transactionIndex"],false)! + transactionLogIndex = try toInt(obj["transactionLogIndex"],false)! type = try toString(obj["type"],false)! } @@ -853,11 +853,10 @@ public struct ZksyncLogs { obj["data"] = RPCObject(data) obj["logIndex"] = RPCObject(logIndex) obj["removed"] = RPCObject(removed) - obj["topics"] = RPCObject(topics) obj["transactionHash"] = RPCObject(transactionHash) obj["transactionIndex"] = RPCObject(transactionIndex) obj["transactionLogIndex"] = RPCObject(transactionLogIndex) obj["type"] = RPCObject(type) return obj } -} \ No newline at end of file +} diff --git a/swift/Sources/In3/Config.swift b/swift/Sources/In3/Config.swift index 991536e15..958eb8f4f 100644 --- a/swift/Sources/In3/Config.swift +++ b/swift/Sources/In3/Config.swift @@ -30,7 +30,7 @@ public struct In3Config : Codable { /// the number in percent needed in order reach finality (% of signature of the validators). /// /// Example: `50` - public var finality : UInt64? + public var finality : Int? /// if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. /// @@ -41,7 +41,7 @@ public struct In3Config : Codable { /// (default: `7`) /// /// Example: `1` - public var maxAttempts : UInt64? + public var maxAttempts : Int? /// if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. /// @@ -84,7 +84,7 @@ public struct In3Config : Codable { /// if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. /// /// Example: `6` - public var replaceLatestBlock : UInt64? + public var replaceLatestBlock : Int? /// if true the nodelist will be automaticly updated if the lastBlock is newer. /// (default: `true`) @@ -94,7 +94,7 @@ public struct In3Config : Codable { /// (default: `1`) /// /// Example: `2` - public var signatureCount : UInt64? + public var signatureCount : Int? /// if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. /// (default: `true`) @@ -110,18 +110,18 @@ public struct In3Config : Codable { /// min stake of the server. Only nodes owning at least this amount will be chosen. /// /// Example: `10000000` - public var minDeposit : UInt64? + public var minDeposit : UInt256? /// used to identify the capabilities of the node. /// - /// Example: `65535` - public var nodeProps : UInt64? + /// Example: `"0xffff"` + public var nodeProps : String? /// the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. /// (default: `2`) /// /// Example: `3` - public var requestCount : UInt64? + public var requestCount : Int? /// url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. /// @@ -205,7 +205,7 @@ public struct In3Config : Codable { /// - Parameter key : the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) /// - Parameter pk : registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) /// - Parameter btc : configure the Bitcoin verification - public init(chainId : String? = nil, finality : UInt64? = nil, includeCode : Bool? = nil, maxAttempts : UInt64? = nil, keepIn3 : Bool? = nil, stats : Bool? = nil, useBinary : Bool? = nil, experimental : Bool? = nil, timeout : UInt64? = nil, proof : String? = nil, replaceLatestBlock : UInt64? = nil, autoUpdateList : Bool? = nil, signatureCount : UInt64? = nil, bootWeights : Bool? = nil, useHttp : Bool? = nil, minDeposit : UInt64? = nil, nodeProps : UInt64? = nil, requestCount : UInt64? = nil, rpc : String? = nil, nodes : Nodes? = nil, zksync : Zksync? = nil, key : String? = nil, pk : String? = nil, btc : Btc? = nil) { + public init(chainId : String? = nil, finality : Int? = nil, includeCode : Bool? = nil, maxAttempts : Int? = nil, keepIn3 : Bool? = nil, stats : Bool? = nil, useBinary : Bool? = nil, experimental : Bool? = nil, timeout : UInt64? = nil, proof : String? = nil, replaceLatestBlock : Int? = nil, autoUpdateList : Bool? = nil, signatureCount : Int? = nil, bootWeights : Bool? = nil, useHttp : Bool? = nil, minDeposit : UInt256? = nil, nodeProps : String? = nil, requestCount : Int? = nil, rpc : String? = nil, nodes : Nodes? = nil, zksync : Zksync? = nil, key : String? = nil, pk : String? = nil, btc : Btc? = nil) { self.chainId = chainId self.finality = finality self.includeCode = includeCode @@ -242,7 +242,7 @@ public struct In3Config : Codable { public var whiteListContract : String? /// manual whitelist. - public var whiteList : String? + public var whiteList : [String]? /// identifier of the registry. public var registryId : String @@ -251,7 +251,7 @@ public struct In3Config : Codable { public var needsUpdate : Bool? /// average block time (seconds) for this chain. - public var avgBlockTime : UInt64? + public var avgBlockTime : Int? /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. public var verifiedHashes : [VerifiedHashes]? @@ -268,7 +268,7 @@ public struct In3Config : Codable { /// - Parameter avgBlockTime : average block time (seconds) for this chain. /// - Parameter verifiedHashes : if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. /// - Parameter nodeList : manual nodeList. As Value a array of Node-Definitions is expected. - public init(contract : String, whiteListContract : String? = nil, whiteList : String? = nil, registryId : String, needsUpdate : Bool? = nil, avgBlockTime : UInt64? = nil, verifiedHashes : [VerifiedHashes]? = nil, nodeList : [NodeList]? = nil) { + public init(contract : String, whiteListContract : String? = nil, whiteList : [String]? = nil, registryId : String, needsUpdate : Bool? = nil, avgBlockTime : Int? = nil, verifiedHashes : [VerifiedHashes]? = nil, nodeList : [NodeList]? = nil) { self.contract = contract self.whiteListContract = whiteListContract self.whiteList = whiteList @@ -308,13 +308,13 @@ public struct In3Config : Codable { public var address : String /// used to identify the capabilities of the node (defaults to 0xFFFF). - public var props : UInt64 + public var props : String /// initialize it memberwise /// - Parameter url : manual nodeList. As Value a array of Node-Definitions is expected. /// - Parameter address : address of the node /// - Parameter props : used to identify the capabilities of the node (defaults to 0xFFFF). - public init(url : String, address : String, props : UInt64) { + public init(url : String, address : String, props : String) { self.url = url self.address = address self.props = props @@ -408,18 +408,18 @@ public struct In3Config : Codable { /// (default: `20`) /// /// Example: `10` - public var maxDAP : UInt64? + public var maxDAP : Int? /// max increase (in percent) of the difference between targets when accepting new targets. /// (default: `10`) /// /// Example: `5` - public var maxDiff : UInt64? + public var maxDiff : Int? /// initialize it memberwise /// - Parameter maxDAP : configure the Bitcoin verification /// - Parameter maxDiff : max increase (in percent) of the difference between targets when accepting new targets. - public init(maxDAP : UInt64? = nil, maxDiff : UInt64? = nil) { + public init(maxDAP : Int? = nil, maxDiff : Int? = nil) { self.maxDAP = maxDAP self.maxDiff = maxDiff } diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index 944cce67a..caf2d5091 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -319,6 +319,11 @@ public enum RPCObject: Equatable { self = .integer(Int(value)) } + /// Wrap a UInt256 as Value + public init(_ value: UInt256) { + self = .string("0x" + value.toString(radix: 16)) + } + /// Wrap a Double as Value public init(_ value: Double) { self = .double(value) diff --git a/swift/Sources/In3/Utils/UInt256.swift b/swift/Sources/In3/Utils/UInt256.swift index 2bae3b9b5..ad75ba81a 100644 --- a/swift/Sources/In3/Utils/UInt256.swift +++ b/swift/Sources/In3/Utils/UInt256.swift @@ -8,35 +8,41 @@ extension mp_int { } } /// a bigint implementation based on tommath to represent big numbers -public class UInt256: CustomStringConvertible, Hashable, Comparable { +/// It is used to represent uint256 values +final public class UInt256: CustomStringConvertible, Hashable, Comparable, Decodable, Encodable { var value = mp_int() + /// creates a empt (0)-value public init() { mp_init_set(&self.value, 0) } - + + /// i nitializes its value from a uint64 type public init(_ v:UInt64) { mp_init_set(&self.value, v) } - - public required convenience init(integerLiteral value: IntegerLiteralType) { - self.init(UInt64(value)) + + /// inits its value from a Int + public required convenience init(_ val: IntegerLiteralType) { + self.init(UInt64(val)) } + + /// copies the value from another UInt256 public init(_ value: UInt256) { mp_init_copy(&self.value, &value.value) } - public func hash(into hasher: inout Hasher) { - toString(radix: 16).hash(into: &hasher) - } - + /// initialze the value from a string. + /// if the string starts with '0x' it will interpreted as radix 16 + /// otherwise the default for the radix is 10 + /// - Parameter radix : the radix or the base to use when parsing the String (10 - decimal, 16 - hex, 2 - binary ... ) public init?(_ val: String, radix: Int = 10) { var r = radix var v = val assert(r >= 2 && r <= 36, "Only radix from 2 to 36 are supported") - if (v.starts(with: "0x")) { + if v.starts(with: "0x") { v = String(v.suffix(from: v.index(v.startIndex, offsetBy: 2))) r = 16 } @@ -46,22 +52,57 @@ public class UInt256: CustomStringConvertible, Hashable, Comparable { } } + /// initializes from a decoder + public init(from decoder: Decoder) throws { + let v = try decoder.singleValueContainer().decode(String.self) + if v.starts(with: "0x") { + if mp_read_radix(&self.value, String(v.suffix(from: v.index(v.startIndex, offsetBy: 2))), Int32(16)) != 0 { + throw IncubedError.convert(message: "Invalid UInt256 values") + } + } else { + throw IncubedError.convert(message: "UInt256 value must start with '0x'") + } + } + + /// encodes the value to a decoder + public func encode(to encoder: Encoder) throws { + var c = encoder.singleValueContainer() + try c.encode(self.hexValue) + } + + + /// hash of the value + public func hash(into hasher: inout Hasher) { + toString(radix: 16).hash(into: &hasher) + } + + /// cleanup freeing the value deinit { mp_clear(&self.value); } - + + /// returns the value as Double (as close as possible) public var doubleValue: Double { return mp_get_double(&self.value) } - + + /// the hex representation staring with '0x' + public var hexValue: String { + return "0x" + self.toString(radix: 16) + } + + /// a unsigned Int representation (if possible) public var uintValue: UInt { return mp_get_int(&self.value) } + /// a unsigned UInt64 representation (if possible) public var uint64Value: UInt64 { return mp_get_long_long(&self.value) } + /// a string representation based on the given radix. + /// - Parameter radix : the radix or the base to use when parsing the String (10 - decimal, 16 - hex, 2 - binary ... ) public func toString(radix: Int = 10) -> String { assert(radix >= 2 && radix <= 36, "invalid radix") @@ -87,7 +128,32 @@ public class UInt256: CustomStringConvertible, Hashable, Comparable { return res } - + public func sub(_ val:UInt256) -> UInt256 { + let res:UInt256 = UInt256() + mp_sub(&self.value, &val.value, &res.value) + return res + } + + public func mul(_ val:UInt256) -> UInt256 { + let res:UInt256 = UInt256() + mp_mul(&self.value, &val.value, &res.value) + return res + } + + public func div(_ val:UInt256) -> UInt256 { + let res:UInt256 = UInt256() + let mod:UInt256 = UInt256() + mp_div(&self.value, &val.value, &res.value, &mod.value) + return res + } + + public func mod(_ val:UInt256) -> UInt256 { + let res:UInt256 = UInt256() + mp_mod(&self.value, &val.value, &res.value) + return res + } + + } public func == (a: UInt256, b: UInt256) -> Bool { @@ -113,3 +179,43 @@ public func <= (a: UInt256, b: UInt256) -> Bool { public func + (a: UInt256, b: UInt256) -> UInt256 { return a.add(b) } + +public func + (a: UInt256, b: Int) -> UInt256 { + return b < 0 ? a.sub(UInt256(-b)) : a.add(UInt256(b)) +} + +public func + (a: UInt256, b: UInt64) -> UInt256 { + return a.add(UInt256(b)) +} + +public func - (a: UInt256, b: UInt256) -> UInt256 { + return a.sub(b) +} + +public func - (a: UInt256, b: Int) -> UInt256 { + return b >= 0 ? a.sub(UInt256(b)) : a.add(UInt256(-b)) +} + +public func - (a: UInt256, b: UInt64) -> UInt256 { + return a.sub(UInt256(b)) +} + +public func / (a: UInt256, b: UInt256) -> UInt256 { + return a.div(b) +} + +public func * (a: UInt256, b: UInt256) -> UInt256 { + return a.mul(b) +} + +public func % (a: UInt256, b: UInt256) -> UInt256 { + return a.mod(b) +} + + +extension UInt64 { + init(_ val:UInt256) { + self = val.uint64Value + } +} + diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index f3de4d099..d69fcaf16 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -17,6 +17,22 @@ final class In3Tests: XCTestCase { else { XCTFail("Could not parse UINt256") } + if let v = UInt256("0x1") { + XCTAssertEqual(v.description,"1") + XCTAssertEqual(v.hexValue,"0x1") + } else { + XCTFail("Could not parse UINt256") + } + if let v = UInt256("0x0") { + XCTAssertEqual(v.description,"0") + XCTAssertEqual(v.hexValue,"0x0") + } else { + XCTFail("Could not parse UINt256") + } + + let a = UInt256(20) + let b = a + 10 + XCTAssertEqual(b.uintValue,30) } From 9940362bc5f4841f3ace8ccdb738ca07617ede8e Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 9 Apr 2021 15:07:52 +0200 Subject: [PATCH 112/221] refactore the rpc-structure --- c/src/api/eth1/rpc.yml | 159 ++-- c/src/core/client/rpc.yml | 2 +- c/src/nodeselect/full/rpc.yml | 9 +- c/src/signer/pk-signer/rpc.yml | 11 +- scripts/_in3.sh | 47 +- scripts/build_rpc_docu.js | 6 +- scripts/generator/swift.js | 11 +- swift/Sources/In3/API/Account.swift | 388 +++++++++ .../In3/API/{BtcAPI.swift => Btc.swift} | 2 +- .../In3/API/{EthAPI.swift => Eth.swift} | 242 ++---- swift/Sources/In3/API/In3API.swift | 760 ------------------ .../In3/API/{IpfsAPI.swift => Ipfs.swift} | 2 +- swift/Sources/In3/API/Nodelist.swift | 325 ++++++++ swift/Sources/In3/API/Utils.swift | 184 +++++ .../In3/API/{ZksyncAPI.swift => Zksync.swift} | 4 +- swift/Sources/In3/In3.swift | 22 +- swift/Sources/In3/Utils/UInt256.swift | 14 +- swift/Tests/In3Tests/In3Tests.swift | 2 +- 18 files changed, 1103 insertions(+), 1087 deletions(-) create mode 100644 swift/Sources/In3/API/Account.swift rename swift/Sources/In3/API/{BtcAPI.swift => Btc.swift} (99%) rename swift/Sources/In3/API/{EthAPI.swift => Eth.swift} (89%) delete mode 100644 swift/Sources/In3/API/In3API.swift rename swift/Sources/In3/API/{IpfsAPI.swift => Ipfs.swift} (99%) create mode 100644 swift/Sources/In3/API/Nodelist.swift create mode 100644 swift/Sources/In3/API/Utils.swift rename swift/Sources/In3/API/{ZksyncAPI.swift => Zksync.swift} (99%) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 522366653..ee3fd8ca1 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -30,7 +30,11 @@ types: -in3: +utils: + + descr: | + a Collection of utility-function. + in3_abiEncode: sync: true @@ -93,31 +97,6 @@ in3: - false response: "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" - - in3_ens: - descr: | - resolves a ens-name. - the domain names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. - For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. - params: - name: - descr: the domain name UTS46 compliant string. - type: string - field: - descr: the required data, which could be one of ( `addr` - the address, `resolver` - the address of the resolver, `hash` - the namehash, `owner` - the owner of the domain) - type: string - optional: true - default: addr - result: - descr: the value of the specified field - example: - request: - - cryptokitties.eth - - addr - response: "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" - - - in3_toWei: sync : true @@ -165,6 +144,73 @@ in3: - 3 response: "0.158" + in3_cacheClear: + sync: true + descr: clears the incubed cache (usually found in the .in3-folder) + result: + descr: true indicating the success + example: + request: [] + response: true + + web3_clientVersion: + descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. + result: + descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. + + keccak: + sync: true + alias: web3_sha3 + + web3_sha3: + sync: true + descr: | + Returns Keccak-256 (not the standardized SHA3-256) of the given data. + + See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + result: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + + sha256: + sync: true + descr: | + Returns sha-256 of the given data. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + result: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + + net_version: + sync: true + descr: the Network Version (currently 1) + result: + descr: the Version number + +account: + descr: | + Account Handling includes handling signers and preparing and signing transacrtion and data. + + Signers are Plugins able to create signatures. Those functions will use the registered plugins. + + in3_pk2address: sync: true descr: extracts the address from a private key. @@ -344,68 +390,7 @@ in3: - test response: "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" - in3_cacheClear: - sync: true - descr: clears the incubed cache (usually found in the .in3-folder) - result: - descr: true indicating the success - example: - request: [] - response: true - -eth: - - web3_clientVersion: - descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. - result: - descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. - - keccak: - sync: true - alias: web3_sha3 - - web3_sha3: - sync: true - descr: | - Returns Keccak-256 (not the standardized SHA3-256) of the given data. - - See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - - No proof needed, since the client will execute this locally. - params: - data: - descr: data to hash - type: bytes - result: - descr: the 32byte hash of the data - example: - request: - - "0x1234567890" - response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - - sha256: - sync: true - descr: | - Returns sha-256 of the given data. - - No proof needed, since the client will execute this locally. - params: - data: - descr: data to hash - type: bytes - result: - descr: the 32byte hash of the data - example: - request: - - "0x1234567890" - response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - net_version: - sync: true - descr: the Network Version (currently 1) - result: - descr: the Version number - in3_createKey: sync: true descr: | diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index f7fea74a1..45bb6352a 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -1,4 +1,4 @@ -in3: +config: descr: | There are also some Incubed specific rpc-methods, which will help the clients to bootstrap and update the nodeLists. diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 7434f454f..2e88044f5 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -1,4 +1,6 @@ -in3: +nodelist: + + descr: special Incubed nodelist-handling functions. Most of those are only used internally. # config config: @@ -127,6 +129,7 @@ in3: # Verified RPCs in3_nodeList: + apiName: nodes descr: fetches and verifies the nodeList from a node params: limit: @@ -144,9 +147,12 @@ in3: optional: true result: + typeName: NodeListDefinition descr: the current nodelist type: nodes: + typeName: Node + array: true descr: a array of node definitions. type: url: @@ -339,6 +345,7 @@ in3: value: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" in3_sign: + apiName: signBlockHash descr: | requests a signed blockhash from the node. In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers diff --git a/c/src/signer/pk-signer/rpc.yml b/c/src/signer/pk-signer/rpc.yml index 34d51cd43..162a25c05 100644 --- a/c/src/signer/pk-signer/rpc.yml +++ b/c/src/signer/pk-signer/rpc.yml @@ -1,4 +1,4 @@ -in3: +account: # config config: @@ -19,6 +19,7 @@ in3: # RPC in3_addRawKey: + sync: true descr: adds a raw private key as signer, which allows signing transactions. params: pk: @@ -33,9 +34,15 @@ in3: response: "0x2e988a386a799f506693793c6a5af6b54dfaabfb" eth_accounts: - descr: returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. + sync: true + descr: | + returns a array of account-addresss the incubed client is able to sign with. + + In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. result: descr: the array of addresses of all registered signers. + array: true + type: address example: response: - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" diff --git a/scripts/_in3.sh b/scripts/_in3.sh index d0e2cf7a9..58ee826db 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -13,6 +13,18 @@ subcmds=( 'createkey: generates a random key' 'in3_checksumAddress: display the address as checksumAddress' 'keccak: calculate the keccak hash of the ' + 'eth_accounts: returns a array of account-addresss the incubed client is able to sign with' + 'eth_sign: The sign method calculates an Ethereum specific signature with: ' + 'eth_signTransaction: Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTrans... ' + 'in3_addRawKey: adds a raw private key as signer, which allows signing transactions ' + 'in3_createKey: Generates 32 random bytes ' + 'in3_decryptKey: decrypts a JSON Keystore file as defined in the ' + 'in3_ecrecover: extracts the public key and address from signature ' + 'in3_pk2address: extracts the address from a private key ' + 'in3_pk2public: extracts the public key from a private key ' + 'in3_prepareTx: prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction ' + 'in3_signData: signs the given data ' + 'in3_signTx: signs the given raw Tx (as prepared by in3_prepareTx ) ' 'btc_proofTarget: Whenever the client is not able to trust the changes of the target (which is the case if a block can... ' 'getbestblockhash: Returns the hash of the best (tip) block in the longest blockchain' 'getblock: Returns data of block for given block hash ' @@ -20,6 +32,7 @@ subcmds=( 'getblockheader: Returns data of block header for given block hash ' 'getdifficulty: Returns the proof-of-work difficulty as a multiple of the minimum difficulty ' 'getrawtransaction: Returns the raw transaction data ' + 'in3_config: changes the configuration of a client ' 'eth_blockNumber: returns the number of the most recent block' 'eth_call: calls a function of a contract (or simply executes the evm opcodes) and returns the result ' 'eth_estimateGas: calculates the gas needed to execute a transaction ' @@ -41,36 +54,22 @@ subcmds=( 'eth_sendRawTransaction: sends or broadcasts a prviously signed raw transaction ' 'eth_sendTransaction: signs and sends a Transaction ' 'eth_sendTransactionAndWait: signs and sends a Transaction, but then waits until the transaction receipt can be verified ' - 'eth_sign: The sign method calculates an Ethereum specific signature with: ' - 'eth_signTransaction: Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTrans... ' - 'in3_createKey: Generates 32 random bytes ' - 'keccak: Returns Keccak-256 (not the standardized SHA3-256) of the given data' - 'net_version: the Network Version (currently 1)' - 'sha256: Returns sha-256 of the given data ' - 'web3_clientVersion: Returns the underlying client version' - 'web3_sha3: Returns Keccak-256 (not the standardized SHA3-256) of the given data ' - 'eth_accounts: returns a array of account-addresss the incubed client is able to sign with' + 'ipfs_get: Fetches the data for a requested ipfs-hash ' + 'ipfs_put: Stores ipfs-content to the ipfs network ' + 'in3_nodeList: fetches and verifies the nodeList from a node ' + 'in3_sign: requests a signed blockhash from the node ' + 'in3_whitelist: Returns whitelisted in3-nodes addresses
' 'in3_abiDecode: based on the ' 'in3_abiEncode: based on the ' - 'in3_addRawKey: adds a raw private key as signer, which allows signing transactions ' 'in3_cacheClear: clears the incubed cache (usually found in the ' 'in3_checksumAddress: Will convert an upper or lowercase Ethereum address to a checksum address
' - 'in3_config: changes the configuration of a client ' - 'in3_decryptKey: decrypts a JSON Keystore file as defined in the ' - 'in3_ecrecover: extracts the public key and address from signature ' - 'in3_ens: resolves a ens-name ' 'in3_fromWei: converts a given uint (also as hex) with a wei-value into a specified unit ' - 'in3_nodeList: fetches and verifies the nodeList from a node ' - 'in3_pk2address: extracts the address from a private key ' - 'in3_pk2public: extracts the public key from a private key ' - 'in3_prepareTx: prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction ' - 'in3_sign: requests a signed blockhash from the node ' - 'in3_signData: signs the given data ' - 'in3_signTx: signs the given raw Tx (as prepared by in3_prepareTx ) ' 'in3_toWei: converts the given value into wei ' - 'in3_whitelist: Returns whitelisted in3-nodes addresses
' - 'ipfs_get: Fetches the data for a requested ipfs-hash ' - 'ipfs_put: Stores ipfs-content to the ipfs network ' + 'keccak: Returns Keccak-256 (not the standardized SHA3-256) of the given data' + 'net_version: the Network Version (currently 1)' + 'sha256: Returns sha-256 of the given data ' + 'web3_clientVersion: Returns the underlying client version' + 'web3_sha3: Returns Keccak-256 (not the standardized SHA3-256) of the given data ' 'zksync_account_address: returns the address of the account used' 'zksync_account_info: returns account_info from the server
' 'zksync_aggregate_pubkey: calculate the public key based on multiple public keys signing together using schnorr musig signatur... ' diff --git a/scripts/build_rpc_docu.js b/scripts/build_rpc_docu.js index 8b42bf564..b7ea573f9 100644 --- a/scripts/build_rpc_docu.js +++ b/scripts/build_rpc_docu.js @@ -121,7 +121,7 @@ function handle_config(conf, pre, title, descr) { scan('../c/src') -docs.in3.in3_config.params.config.type = config +docs.config.in3_config.params.config.type = config rpc_doc.push('# API RPC\n\n') rpc_doc.push('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') config_doc.push('# Configuration\n\n') @@ -216,8 +216,10 @@ for (const s of Object.keys(docs).sort()) { z += "'" zsh_cmds.push(z) } + console.log('generate ' + s + '\n ' + Object.keys(rpcs).join('\n ')) - swift.generateAPI(s, rpcs, rdescr, types) + if (Object.values(rpcs).filter(_ => !_.skipApi).length) + swift.generateAPI(s, rpcs, rdescr, types) } diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index c2cdfd5ca..558d9c80f 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -91,15 +91,15 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api } function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { - let swiftType = camelCaseUp(('' + c.type).split('|')[0].trim()) + let swiftType = camelCaseUp(('' + (c.typeName || c.type)).split('|')[0].trim()) let typedef = null if (typeof c.type === 'object') { typedef = getType(c.type, typeConfigs) - swiftType = camelCaseUp(api + camelCaseUp(c.typeName || prefix.startsWith('get') ? prefix.substr(3) : prefix)) + swiftType = c.typeName || camelCaseUp(api + camelCaseUp(c.typeName || prefix.startsWith('get') ? prefix.substr(3) : prefix)) } else if (typeConfigs[c.type]) { typedef = getType(c.type, typeConfigs) - swiftType = camelCaseUp((c.type.toLowerCase().startsWith(api.toLowerCase()) ? '' : api) + camelCaseUp(c.type)) + swiftType = c.typeName || camelCaseUp((c.type.toLowerCase().startsWith(api.toLowerCase()) ? '' : api) + camelCaseUp(c.type)) } else if (swiftType == 'Uint') swiftType = 'UInt64' else if (swiftType.startsWith('Uint')) swiftType = swiftType.replace('Uint', 'UInt') @@ -255,6 +255,9 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc s += '\n return try execLocalAndConvert(in3: in3, method: "' + rpc_name + '",' + params if (returnType == '[AnyObject]') s += ' convertWith: { try toArray($0,$1)! } )' + else if (r.array) { + s += ' convertWith: { try toArray($0,$1)!.map({ try ' + converterName(returnType, true) + '($0, ' + (!!r.optional) + ')! }) } )' + } else s += ' convertWith: ' + converterName(returnType, true) + ' )' s += '\n }\n' @@ -307,7 +310,7 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc exports.generateAPI = function (api_name, rpcs, descr, types) { const structs = {} - const apiName = camelCaseUp(api_name) + 'API' + const apiName = camelCaseUp(api_name) const content = [ '/// this is generated file don\'t edit it manually!', '', diff --git a/swift/Sources/In3/API/Account.swift b/swift/Sources/In3/API/Account.swift new file mode 100644 index 000000000..ced37b033 --- /dev/null +++ b/swift/Sources/In3/API/Account.swift @@ -0,0 +1,388 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// Account Handling includes handling signers and preparing and signing transacrtion and data. +/// +/// Signers are Plugins able to create signatures. Those functions will use the registered plugins. +/// +public class Account { + internal var in3: In3 + + /// initialiazes the Account API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// extracts the address from a private key. + /// - Parameter pk : the 32 bytes private key as hex. + /// - Returns: the address + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// // result = "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" + /// ``` + /// + public func pk2address(pk: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_pk2address", params:RPCObject( pk), convertWith: toString ) + } + + /// extracts the public key from a private key. + /// - Parameter pk : the 32 bytes private key as hex. + /// - Returns: the public key as 64 bytes + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// // result = "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f7818\ + /// // 6577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" + /// ``` + /// + public func pk2public(pk: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_pk2public", params:RPCObject( pk), convertWith: toString ) + } + + /// extracts the public key and address from signature. + /// - Parameter msg : the message the signature is based on. + /// - Parameter sig : the 65 bytes signature as hex. + /// - Parameter sigtype : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw` + /// - Returns: the extracted public key and address + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") + /// // result = + /// // publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c\ + /// // 4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" + /// // address: "0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4" + /// ``` + /// + public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> AccountEcrecover { + return try execLocalAndConvert(in3: in3, method: "in3_ecrecover", params:RPCObject( msg), RPCObject( sig), sigtype == nil ? RPCObject.none : RPCObject( sigtype! ), convertWith: { try AccountEcrecover($0,$1) } ) + } + + /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. + /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). + /// - Returns: the unsigned raw transaction as hex. + /// + /// **Example** + /// + /// ```swift + /// AccountAPI(in3).prepareTx(tx: AccountTransaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a0850100000000\ + /// // 80018080" + /// } + /// } + /// + /// ``` + /// + public func prepareTx(tx: AccountTransaction) -> Future { + return execAndConvert(in3: in3, method: "in3_prepareTx", params:RPCObject( tx.toRPCDict()), convertWith: toString ) + } + + /// signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. + /// - Parameter tx : the raw unsigned transactiondata + /// - Parameter from : the account to sign + /// - Returns: the raw transaction with signature. + /// + /// **Example** + /// + /// ```swift + /// AccountAPI(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xf86980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a08501000000\ + /// // 008026a03c5b094078383f3da3f65773ab1314e89ee76bc41f827f2ef211b2d3449e4435a077755\ + /// // f8d9b32966e1ad8f6c0e8c9376a4387ed237bdbf2db6e6b94016407e276" + /// } + /// } + /// + /// ``` + /// + public func signTx(tx: String, from: String) -> Future { + return execAndConvert(in3: in3, method: "in3_signTx", params:RPCObject( tx), RPCObject( from), convertWith: toString ) + } + + /// signs the given data. + /// - Parameter msg : the message to sign. + /// - Parameter account : the account to sign if the account is a bytes32 it will be used as private key + /// - Parameter msgType : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data) + /// - Returns: the signature + /// + /// **Example** + /// + /// ```swift + /// AccountAPI(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // message: "0x0102030405060708090a0b0c0d0e0f" + /// // messageHash: "0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67" + /// // signature: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792\ + /// // 264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b" + /// // r: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579" + /// // s: "0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152" + /// // v: 27 + /// } + /// } + /// + /// ``` + /// + public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { + return execAndConvert(in3: in3, method: "in3_signData", params:RPCObject( msg), RPCObject( account), msgType == nil ? RPCObject.none : RPCObject( msgType! ), convertWith: { try AccountSignData($0,$1) } ) + } + + /// decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. + /// - Parameter key : Keydata as object as defined in the keystorefile + /// - Parameter passphrase : the password to decrypt it. + /// - Returns: a raw private key (32 bytes) + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") + /// // result = "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" + /// ``` + /// + public func decryptKey(key: String, passphrase: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_decryptKey", params:RPCObject( key), RPCObject( passphrase), convertWith: toString ) + } + + /// Generates 32 random bytes. + /// If /dev/urandom is available it will be used and should generate a secure random number. + /// If not the number should not be considered sceure or used in production. + /// + /// - Parameter seed : the seed. If given the result will be deterministic. + /// - Returns: the 32byte random data + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).createKey() + /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + /// ``` + /// + public func createKey(seed: String? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_createKey", params:seed == nil ? RPCObject.none : RPCObject( seed! ), convertWith: toString ) + } + + /// The sign method calculates an Ethereum specific signature with: + /// + /// ```js + /// sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). + /// ``` + /// + /// By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. + /// + /// For the address to sign a signer must be registered. + /// + /// - Parameter account : the account to sign with + /// - Parameter message : the message to sign + /// - Returns: the signature (65 bytes) for the given message. + /// + /// **Example** + /// + /// ```swift + /// AccountAPI(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ + /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" + /// } + /// } + /// + /// ``` + /// + public func sign(account: String, message: String) -> Future { + return execAndConvert(in3: in3, method: "eth_sign", params:RPCObject( account), RPCObject( message), convertWith: toString ) + } + + /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. + /// - Parameter tx : transaction to sign + /// - Returns: the raw signed transaction + /// + /// **Example** + /// + /// ```swift + /// AccountAPI(in3).signTransaction(tx: AccountTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ + /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" + /// } + /// } + /// + /// ``` + /// + public func signTransaction(tx: AccountTransaction) -> Future { + return execAndConvert(in3: in3, method: "eth_signTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) + } + + /// adds a raw private key as signer, which allows signing transactions. + /// - Parameter pk : the 32byte long private key as hex string. + /// - Returns: the address of given key. + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") + /// // result = "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + /// ``` + /// + public func addRawKey(pk: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_addRawKey", params:RPCObject( pk), convertWith: toString ) + } + + /// returns a array of account-addresss the incubed client is able to sign with. + /// + /// In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. + /// + /// - Returns: the array of addresses of all registered signers. + /// + /// **Example** + /// + /// ```swift + /// let result = try AccountAPI(in3).accounts() + /// // result = + /// // - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" + /// // - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" + /// ``` + /// + public func accounts() throws -> [String] { + return try execLocalAndConvert(in3: in3, method: "eth_accounts", convertWith: { try toArray($0,$1)!.map({ try toString($0, false)! }) } ) + } + + +} +/// the extracted public key and address +public struct AccountEcrecover { + /// the public Key of the signer (64 bytes) + public var publicKey: String + + /// the address + public var address: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + publicKey = try toString(obj["publicKey"],false)! + address = try toString(obj["address"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["publicKey"] = RPCObject(publicKey) + obj["address"] = RPCObject(address) + return obj + } +} + +/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). +public struct AccountTransaction { + /// receipient of the transaction. + public var to: String + + /// sender of the address (if not sepcified, the first signer will be the sender) + public var from: String + + /// value in wei to send + public var value: UInt256? + + /// the gas to be send along + public var gas: UInt64? + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64? + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64? + + /// the data-section of the transaction + public var data: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],false)! + value = try toUInt256(obj["value"],true)! + gas = try toUInt64(obj["gas"],true)! + gasPrice = try toUInt64(obj["gasPrice"],true)! + nonce = try toUInt64(obj["nonce"],true)! + data = try toString(obj["data"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = RPCObject(from) + obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) + obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) + obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) + obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) + obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + return obj + } +} + +/// the signature +public struct AccountSignData { + /// original message used + public var message: String + + /// the hash the signature is based on + public var messageHash: String + + /// the signature (65 bytes) + public var signature: String + + /// the x-value of the EC-Point + public var r: String + + /// the y-value of the EC-Point + public var s: String + + /// the recovery value (0|1) + 27 + public var v: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + message = try toString(obj["message"],false)! + messageHash = try toString(obj["messageHash"],false)! + signature = try toString(obj["signature"],false)! + r = try toString(obj["r"],false)! + s = try toString(obj["s"],false)! + v = try toString(obj["v"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["message"] = RPCObject(message) + obj["messageHash"] = RPCObject(messageHash) + obj["signature"] = RPCObject(signature) + obj["r"] = RPCObject(r) + obj["s"] = RPCObject(s) + obj["v"] = RPCObject(v) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/API/BtcAPI.swift b/swift/Sources/In3/API/Btc.swift similarity index 99% rename from swift/Sources/In3/API/BtcAPI.swift rename to swift/Sources/In3/API/Btc.swift index e77c356f8..2c65bb4a8 100644 --- a/swift/Sources/In3/API/BtcAPI.swift +++ b/swift/Sources/In3/API/Btc.swift @@ -16,7 +16,7 @@ import Foundation /// * **cbtx** /// * **cbtxMerkleProof** /// -public class BtcAPI { +public class Btc { internal var in3: In3 /// initialiazes the Btc API diff --git a/swift/Sources/In3/API/EthAPI.swift b/swift/Sources/In3/API/Eth.swift similarity index 89% rename from swift/Sources/In3/API/EthAPI.swift rename to swift/Sources/In3/API/Eth.swift index 231ca04f9..6c2e8f448 100644 --- a/swift/Sources/In3/API/EthAPI.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -28,7 +28,7 @@ import Foundation /// * **txIndex** `integer` - The transactionIndex within the block (for transaactions and receipts). /// * **signatures** `Signature[]` - Requested signatures. /// -public class EthAPI { +public class Eth { internal var in3: In3 /// initialiazes the Eth API @@ -37,152 +37,6 @@ public class EthAPI { self.in3 = in3 } - /// Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. - /// - Returns: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. - public func clientVersion() -> Future { - return execAndConvert(in3: in3, method: "web3_clientVersion", convertWith: toString ) - } - - /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. - /// - /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try EthAPI(in3).keccak(data: "0x1234567890") - /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - /// ``` - /// - public func keccak(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "keccak", params:RPCObject( data), convertWith: toString ) - } - - /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. - /// - /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try EthAPI(in3).sha3(data: "0x1234567890") - /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - /// ``` - /// - public func sha3(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "web3_sha3", params:RPCObject( data), convertWith: toString ) - } - - /// Returns sha-256 of the given data. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try EthAPI(in3).sha256(data: "0x1234567890") - /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - /// ``` - /// - public func sha256(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "sha256", params:RPCObject( data), convertWith: toString ) - } - - /// the Network Version (currently 1) - /// - Returns: the Version number - public func version() throws -> String { - return try execLocalAndConvert(in3: in3, method: "net_version", convertWith: toString ) - } - - /// Generates 32 random bytes. - /// If /dev/urandom is available it will be used and should generate a secure random number. - /// If not the number should not be considered sceure or used in production. - /// - /// - Parameter seed : the seed. If given the result will be deterministic. - /// - Returns: the 32byte random data - /// - /// **Example** - /// - /// ```swift - /// let result = try EthAPI(in3).createKey() - /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - /// ``` - /// - public func createKey(seed: String? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_createKey", params:seed == nil ? RPCObject.none : RPCObject( seed! ), convertWith: toString ) - } - - /// The sign method calculates an Ethereum specific signature with: - /// - /// ```js - /// sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). - /// ``` - /// - /// By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. - /// - /// For the address to sign a signer must be registered. - /// - /// - Parameter account : the account to sign with - /// - Parameter message : the message to sign - /// - Returns: the signature (65 bytes) for the given message. - /// - /// **Example** - /// - /// ```swift - /// EthAPI(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ - /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" - /// } - /// } - /// - /// ``` - /// - public func sign(account: String, message: String) -> Future { - return execAndConvert(in3: in3, method: "eth_sign", params:RPCObject( account), RPCObject( message), convertWith: toString ) - } - - /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. - /// - Parameter tx : transaction to sign - /// - Returns: the raw signed transaction - /// - /// **Example** - /// - /// ```swift - /// EthAPI(in3).signTransaction(tx: EthTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ - /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" - /// } - /// } - /// - /// ``` - /// - public func signTransaction(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_signTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) - } - /// returns the number of the most recent block. /// /// See [eth_blockNumber](https://eth.wiki/json-rpc/API#eth_blockNumber) for spec. @@ -774,53 +628,6 @@ public class EthAPI { } -/// transaction to sign -public struct EthTransaction { - /// receipient of the transaction. - public var to: String - - /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String - - /// value in wei to send - public var value: UInt256? - - /// the gas to be send along - public var gas: UInt64? - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64? - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64? - - /// the data-section of the transaction - public var data: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],false)! - value = try toUInt256(obj["value"],true)! - gas = try toUInt64(obj["gas"],true)! - gasPrice = try toUInt64(obj["gasPrice"],true)! - nonce = try toUInt64(obj["nonce"],true)! - data = try toString(obj["data"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = RPCObject(from) - obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) - obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) - obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) - obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) - obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) - return obj - } -} - /// the blockdata, or in case the block with that number does not exist, `null` will be returned. public struct EthBlockdataWithTxHashes { /// Array of transaction hashes @@ -1153,6 +960,53 @@ public struct EthFilter { } } +/// the transactiondata to send +public struct EthTransaction { + /// receipient of the transaction. + public var to: String + + /// sender of the address (if not sepcified, the first signer will be the sender) + public var from: String + + /// value in wei to send + public var value: UInt256? + + /// the gas to be send along + public var gas: UInt64? + + /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + public var gasPrice: UInt64? + + /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + public var nonce: UInt64? + + /// the data-section of the transaction + public var data: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + to = try toString(obj["to"],false)! + from = try toString(obj["from"],false)! + value = try toUInt256(obj["value"],true)! + gas = try toUInt64(obj["gas"],true)! + gasPrice = try toUInt64(obj["gasPrice"],true)! + nonce = try toUInt64(obj["nonce"],true)! + data = try toString(obj["data"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["to"] = RPCObject(to) + obj["from"] = RPCObject(from) + obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) + obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) + obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) + obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) + obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + return obj + } +} + /// the transactionReceipt public struct EthTransactionReceipt { /// the blockNumber diff --git a/swift/Sources/In3/API/In3API.swift b/swift/Sources/In3/API/In3API.swift deleted file mode 100644 index dbd3ca206..000000000 --- a/swift/Sources/In3/API/In3API.swift +++ /dev/null @@ -1,760 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// There are also some Incubed specific rpc-methods, which will help the clients to bootstrap and update the nodeLists. -/// -/// -/// The incubed client itself offers special RPC-Methods, which are mostly handled directly inside the client: -/// -public class In3API { - internal var in3: In3 - - /// initialiazes the In3 API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. - /// - Parameter signature : the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. - /// - Parameter params : a array of arguments. the number of arguments must match the arguments in the signature. - /// - Returns: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) - /// // result = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" - /// ``` - /// - public func abiEncode(signature: String, params: [AnyObject]) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_abiEncode", params:RPCObject( signature), RPCObject( params), convertWith: toString ) - } - - /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. - /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. - /// - Parameter data : the data to decode (usually the result of a eth_call) - /// - Returns: a array with the values after decodeing. - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") - /// // result = - /// // - "0x1234567890123456789012345678901234567890" - /// // - "0x05" - /// ``` - /// - public func abiDecode(signature: String, data: String) throws -> [RPCObject] { - return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), convertWith: { try toArray($0,$1)! } ) - } - - /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) - /// - Parameter address : the address to convert. - /// - Parameter useChainId : if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) - /// - Returns: the address-string using the upper/lowercase hex characters. - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) - /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" - /// ``` - /// - public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress", params:RPCObject( address), useChainId == nil ? RPCObject.none : RPCObject( useChainId! ), convertWith: toString ) - } - - /// resolves a ens-name. - /// the domain names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. - /// For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names. - /// - /// - Parameter name : the domain name UTS46 compliant string. - /// - Parameter field : the required data, which could be one of ( `addr` - the address, `resolver` - the address of the resolver, `hash` - the namehash, `owner` - the owner of the domain) - /// - Returns: the value of the specified field - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).ens(name: "cryptokitties.eth", field: "addr") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" - /// } - /// } - /// - /// ``` - /// - public func ens(name: String, field: String? = "addr") -> Future { - return execAndConvert(in3: in3, method: "in3_ens", params:RPCObject( name), field == nil ? RPCObject.none : RPCObject( field! ), convertWith: toString ) - } - - /// converts the given value into wei. - /// - Parameter value : the value, which may be floating number as string - /// - Parameter unit : the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` - /// - Returns: the value in wei as hex. - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).toWei(value: "20.0009123", unit: "eth") - /// // result = "0x01159183c4793db800" - /// ``` - /// - public func toWei(value: String, unit: String? = "eth") throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_toWei", params:RPCObject( value), unit == nil ? RPCObject.none : RPCObject( unit! ), convertWith: toString ) - } - - /// converts a given uint (also as hex) with a wei-value into a specified unit. - /// - Parameter value : the value in wei - /// - Parameter unit : the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` - /// - Parameter digits : fix number of digits after the comma. If left out, only as many as needed will be included. - /// - Returns: the value as string. - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) - /// // result = "0.158" - /// ``` - /// - public func fromWei(value: UInt256, unit: String, digits: Int? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_fromWei", params:RPCObject( value), RPCObject( unit), digits == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", digits!) ), convertWith: toString ) - } - - /// extracts the address from a private key. - /// - Parameter pk : the 32 bytes private key as hex. - /// - Returns: the address - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") - /// // result = "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" - /// ``` - /// - public func pk2address(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2address", params:RPCObject( pk), convertWith: toString ) - } - - /// extracts the public key from a private key. - /// - Parameter pk : the 32 bytes private key as hex. - /// - Returns: the public key as 64 bytes - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") - /// // result = "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f7818\ - /// // 6577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" - /// ``` - /// - public func pk2public(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2public", params:RPCObject( pk), convertWith: toString ) - } - - /// extracts the public key and address from signature. - /// - Parameter msg : the message the signature is based on. - /// - Parameter sig : the 65 bytes signature as hex. - /// - Parameter sigtype : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw` - /// - Returns: the extracted public key and address - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") - /// // result = - /// // publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c\ - /// // 4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" - /// // address: "0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4" - /// ``` - /// - public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> In3Ecrecover { - return try execLocalAndConvert(in3: in3, method: "in3_ecrecover", params:RPCObject( msg), RPCObject( sig), sigtype == nil ? RPCObject.none : RPCObject( sigtype! ), convertWith: { try In3Ecrecover($0,$1) } ) - } - - /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. - /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Returns: the unsigned raw transaction as hex. - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).prepareTx(tx: In3Transaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a0850100000000\ - /// // 80018080" - /// } - /// } - /// - /// ``` - /// - public func prepareTx(tx: In3Transaction) -> Future { - return execAndConvert(in3: in3, method: "in3_prepareTx", params:RPCObject( tx.toRPCDict()), convertWith: toString ) - } - - /// signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. - /// - Parameter tx : the raw unsigned transactiondata - /// - Parameter from : the account to sign - /// - Returns: the raw transaction with signature. - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xf86980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a08501000000\ - /// // 008026a03c5b094078383f3da3f65773ab1314e89ee76bc41f827f2ef211b2d3449e4435a077755\ - /// // f8d9b32966e1ad8f6c0e8c9376a4387ed237bdbf2db6e6b94016407e276" - /// } - /// } - /// - /// ``` - /// - public func signTx(tx: String, from: String) -> Future { - return execAndConvert(in3: in3, method: "in3_signTx", params:RPCObject( tx), RPCObject( from), convertWith: toString ) - } - - /// signs the given data. - /// - Parameter msg : the message to sign. - /// - Parameter account : the account to sign if the account is a bytes32 it will be used as private key - /// - Parameter msgType : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data) - /// - Returns: the signature - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // message: "0x0102030405060708090a0b0c0d0e0f" - /// // messageHash: "0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67" - /// // signature: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792\ - /// // 264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b" - /// // r: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579" - /// // s: "0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152" - /// // v: 27 - /// } - /// } - /// - /// ``` - /// - public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { - return execAndConvert(in3: in3, method: "in3_signData", params:RPCObject( msg), RPCObject( account), msgType == nil ? RPCObject.none : RPCObject( msgType! ), convertWith: { try In3SignData($0,$1) } ) - } - - /// decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. - /// - Parameter key : Keydata as object as defined in the keystorefile - /// - Parameter passphrase : the password to decrypt it. - /// - Returns: a raw private key (32 bytes) - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") - /// // result = "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" - /// ``` - /// - public func decryptKey(key: String, passphrase: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_decryptKey", params:RPCObject( key), RPCObject( passphrase), convertWith: toString ) - } - - /// clears the incubed cache (usually found in the .in3-folder) - /// - Returns: true indicating the success - /// - /// **Example** - /// - /// ```swift - /// let result = try In3API(in3).cacheClear() - /// // result = true - /// ``` - /// - public func cacheClear() throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_cacheClear", convertWith: toString ) - } - - /// fetches and verifies the nodeList from a node - /// - Parameter limit : if the number is defined and >0 this method will return a partial nodeList limited to the given number. - /// - Parameter seed : this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. - /// - Parameter addresses : a optional array of addresses of signers the nodeList must include. - /// - Returns: the current nodelist - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).nodeList(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // totalServers: 5 - /// // contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" - /// // registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - /// // lastBlockNumber: 8669495 - /// // nodes: - /// // - url: https://in3-v2.slock.it/mainnet/nd-3 - /// // address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" - /// // index: 2 - /// // deposit: "10000000000000000" - /// // props: 29 - /// // timeout: 3600 - /// // registerTime: 1570109570 - /// // weight: 2000 - /// // proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" - /// // - url: https://in3-v2.slock.it/mainnet/nd-5 - /// // address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" - /// // index: 4 - /// // deposit: "10000000000000000" - /// // props: 29 - /// // timeout: 3600 - /// // registerTime: 1570109690 - /// // weight: 2000 - /// // proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" - /// } - /// } - /// - /// ``` - /// - public func nodeList(limit: Int? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { - return execAndConvert(in3: in3, method: "in3_nodeList", params:limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), seed == nil ? RPCObject.none : RPCObject( seed! ), addresses == nil ? RPCObject.none : RPCObject( addresses! ), convertWith: { try In3NodeList($0,$1) } ) - } - - /// requests a signed blockhash from the node. - /// In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers - /// and the processising nodes will then aquire the signatures with this method from the other nodes. - /// - /// Since each node has a risk of signing a wrong blockhash and getting convicted and losing its deposit, - /// per default nodes will and should not sign blockHash of the last `minBlockHeight` (default: 6) blocks! - /// - /// - Parameter blocks : array of requested blocks. - /// - Returns: the Array with signatures of all the requires blocks. - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).sign(blocks: In3Blocks(blockNumber: 8770580)) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // - blockHash: "0xd8189793f64567992eaadefc51834f3d787b03e9a6850b8b9b8003d8d84a76c8" - /// // block: 8770580 - /// // r: "0x954ed45416e97387a55b2231bff5dd72e822e4a5d60fa43bc9f9e49402019337" - /// // s: "0x277163f586585092d146d0d6885095c35c02b360e4125730c52332cf6b99e596" - /// // v: 28 - /// // msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" - /// } - /// } - /// - /// ``` - /// - public func sign(blocks: In3Blocks) -> Future { - return execAndConvert(in3: in3, method: "in3_sign", params:RPCObject( blocks.toRPCDict()), convertWith: { try In3Sign($0,$1) } ) - } - - /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. - /// - Parameter address : address of whitelist contract - /// - Returns: the whitelisted addresses - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // totalServers: 2 - /// // contract: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" - /// // lastBlockNumber: 1546354 - /// // nodes: - /// // - "0x1fe2e9bf29aa1938859af64c413361227d04059a" - /// // - "0x45d45e6ff99e6c34a235d263965910298985fcfe" - /// } - /// } - /// - /// ``` - /// - public func whitelist(address: String) -> Future { - return execAndConvert(in3: in3, method: "in3_whitelist", params:RPCObject( address), convertWith: { try In3Whitelist($0,$1) } ) - } - - /// adds a raw private key as signer, which allows signing transactions. - /// - Parameter pk : the 32byte long private key as hex string. - /// - Returns: the address of given key. - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x2e988a386a799f506693793c6a5af6b54dfaabfb" - /// } - /// } - /// - /// ``` - /// - public func addRawKey(pk: String) -> Future { - return execAndConvert(in3: in3, method: "in3_addRawKey", params:RPCObject( pk), convertWith: toString ) - } - - /// returns a array of account-addresss the incubed client is able to sign with. In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. - /// - Returns: the array of addresses of all registered signers. - /// - /// **Example** - /// - /// ```swift - /// In3API(in3).accounts() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" - /// // - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" - /// } - /// } - /// - /// ``` - /// - public func accounts() -> Future { - return execAndConvert(in3: in3, method: "eth_accounts", convertWith: toString ) - } - - -} -/// the extracted public key and address -public struct In3Ecrecover { - /// the public Key of the signer (64 bytes) - public var publicKey: String - - /// the address - public var address: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - publicKey = try toString(obj["publicKey"],false)! - address = try toString(obj["address"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["publicKey"] = RPCObject(publicKey) - obj["address"] = RPCObject(address) - return obj - } -} - -/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). -public struct In3Transaction { - /// receipient of the transaction. - public var to: String - - /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String - - /// value in wei to send - public var value: UInt256? - - /// the gas to be send along - public var gas: UInt64? - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64? - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64? - - /// the data-section of the transaction - public var data: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],false)! - value = try toUInt256(obj["value"],true)! - gas = try toUInt64(obj["gas"],true)! - gasPrice = try toUInt64(obj["gasPrice"],true)! - nonce = try toUInt64(obj["nonce"],true)! - data = try toString(obj["data"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = RPCObject(from) - obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) - obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) - obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) - obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) - obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) - return obj - } -} - -/// the signature -public struct In3SignData { - /// original message used - public var message: String - - /// the hash the signature is based on - public var messageHash: String - - /// the signature (65 bytes) - public var signature: String - - /// the x-value of the EC-Point - public var r: String - - /// the y-value of the EC-Point - public var s: String - - /// the recovery value (0|1) + 27 - public var v: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - message = try toString(obj["message"],false)! - messageHash = try toString(obj["messageHash"],false)! - signature = try toString(obj["signature"],false)! - r = try toString(obj["r"],false)! - s = try toString(obj["s"],false)! - v = try toString(obj["v"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["message"] = RPCObject(message) - obj["messageHash"] = RPCObject(messageHash) - obj["signature"] = RPCObject(signature) - obj["r"] = RPCObject(r) - obj["s"] = RPCObject(s) - obj["v"] = RPCObject(v) - return obj - } -} - -/// the current nodelist -public struct In3NodeList { - /// a array of node definitions. - public var nodes: In3Nodes - - /// the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. - public var contract: String - - /// the registryId (32 bytes) of the contract, which is there to verify the correct contract. - public var registryId: String - - /// the blockNumber of the last change of the list (usually the last event). - public var lastBlockNumber: UInt64 - - /// the total numbers of nodes. - public var totalServer: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - nodes = try In3Nodes(obj["nodes"],false)! - contract = try toString(obj["contract"],false)! - registryId = try toString(obj["registryId"],false)! - lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! - totalServer = try toUInt64(obj["totalServer"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["contract"] = RPCObject(contract) - obj["registryId"] = RPCObject(registryId) - obj["lastBlockNumber"] = RPCObject(lastBlockNumber) - obj["totalServer"] = RPCObject(totalServer) - return obj - } -} - -/// a array of node definitions. -public struct In3Nodes { - /// the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. - public var url: String - - /// the address of the signer - public var address: String - - /// the index within the nodeList of the contract - public var index: UInt64 - - /// the stored deposit - public var deposit: UInt256 - - /// the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - public var props: String - - /// the time in seconds describing how long the deposit would be locked when trying to unregister a node. - public var timeout: UInt64 - - /// unix timestamp in seconds when the node has registered. - public var registerTime: UInt64 - - /// the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. - public var weight: UInt64 - - /// a hash value containing the above values. - /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof - /// per node instead of verifying each property as its own storage value. - /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` - /// - public var proofHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - url = try toString(obj["url"],false)! - address = try toString(obj["address"],false)! - index = try toUInt64(obj["index"],false)! - deposit = try toUInt256(obj["deposit"],false)! - props = try toString(obj["props"],false)! - timeout = try toUInt64(obj["timeout"],false)! - registerTime = try toUInt64(obj["registerTime"],false)! - weight = try toUInt64(obj["weight"],false)! - proofHash = try toString(obj["proofHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["url"] = RPCObject(url) - obj["address"] = RPCObject(address) - obj["index"] = RPCObject(index) - obj["deposit"] = RPCObject(deposit) - obj["props"] = RPCObject(props) - obj["timeout"] = RPCObject(timeout) - obj["registerTime"] = RPCObject(registerTime) - obj["weight"] = RPCObject(weight) - obj["proofHash"] = RPCObject(proofHash) - return obj - } -} - -/// array of requested blocks. -public struct In3Blocks { - /// the blockNumber to sign - public var blockNumber: UInt64 - - /// the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. - public var hash: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockNumber = try toUInt64(obj["blockNumber"],false)! - hash = try toString(obj["hash"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject(blockNumber) - obj["hash"] = hash == nil ? RPCObject.none : RPCObject(hash!) - return obj - } -} - -/// the Array with signatures of all the requires blocks. -public struct In3Sign { - /// the blockhash which was signed. - public var blockHash: String - - /// the blocknumber - public var block: UInt64 - - /// r-value of the signature - public var r: String - - /// s-value of the signature - public var s: String - - /// v-value of the signature - public var v: String - - /// the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` - public var msgHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockHash = try toString(obj["blockHash"],false)! - block = try toUInt64(obj["block"],false)! - r = try toString(obj["r"],false)! - s = try toString(obj["s"],false)! - v = try toString(obj["v"],false)! - msgHash = try toString(obj["msgHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockHash"] = RPCObject(blockHash) - obj["block"] = RPCObject(block) - obj["r"] = RPCObject(r) - obj["s"] = RPCObject(s) - obj["v"] = RPCObject(v) - obj["msgHash"] = RPCObject(msgHash) - return obj - } -} - -/// the whitelisted addresses -public struct In3Whitelist { - /// array of whitelisted nodes addresses. - public var nodes: String - - /// the blockNumber of the last change of the in3 white list event. - public var lastWhiteList: UInt64 - - /// whitelist contract address. - public var contract: String - - /// the blockNumber of the last change of the list (usually the last event). - public var lastBlockNumber: UInt64 - - /// the total numbers of whitelist nodes. - public var totalServer: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - nodes = try toString(obj["nodes"],false)! - lastWhiteList = try toUInt64(obj["lastWhiteList"],false)! - contract = try toString(obj["contract"],false)! - lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! - totalServer = try toUInt64(obj["totalServer"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["nodes"] = RPCObject(nodes) - obj["lastWhiteList"] = RPCObject(lastWhiteList) - obj["contract"] = RPCObject(contract) - obj["lastBlockNumber"] = RPCObject(lastBlockNumber) - obj["totalServer"] = RPCObject(totalServer) - return obj - } -} \ No newline at end of file diff --git a/swift/Sources/In3/API/IpfsAPI.swift b/swift/Sources/In3/API/Ipfs.swift similarity index 99% rename from swift/Sources/In3/API/IpfsAPI.swift rename to swift/Sources/In3/API/Ipfs.swift index 62d48fc2b..c9db9028c 100644 --- a/swift/Sources/In3/API/IpfsAPI.swift +++ b/swift/Sources/In3/API/Ipfs.swift @@ -6,7 +6,7 @@ import Foundation /// /// Fetching ipfs-content can be easily verified by creating the ipfs-hash based on the received data and comparing it to the requested ipfs-hash. Since there is no chance of manipulating the data, there is also no need to put a deposit or convict a node. That's why the registry-contract allows a zero-deposit fot ipfs-nodes. /// -public class IpfsAPI { +public class Ipfs { internal var in3: In3 /// initialiazes the Ipfs API diff --git a/swift/Sources/In3/API/Nodelist.swift b/swift/Sources/In3/API/Nodelist.swift new file mode 100644 index 000000000..73b309593 --- /dev/null +++ b/swift/Sources/In3/API/Nodelist.swift @@ -0,0 +1,325 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// special Incubed nodelist-handling functions. Most of those are only used internally. +public class Nodelist { + internal var in3: In3 + + /// initialiazes the Nodelist API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// fetches and verifies the nodeList from a node + /// - Parameter limit : if the number is defined and >0 this method will return a partial nodeList limited to the given number. + /// - Parameter seed : this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. + /// - Parameter addresses : a optional array of addresses of signers the nodeList must include. + /// - Returns: the current nodelist + /// + /// **Example** + /// + /// ```swift + /// NodelistAPI(in3).nodes(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // totalServers: 5 + /// // contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" + /// // registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" + /// // lastBlockNumber: 8669495 + /// // nodes: + /// // - url: https://in3-v2.slock.it/mainnet/nd-3 + /// // address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" + /// // index: 2 + /// // deposit: "10000000000000000" + /// // props: 29 + /// // timeout: 3600 + /// // registerTime: 1570109570 + /// // weight: 2000 + /// // proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" + /// // - url: https://in3-v2.slock.it/mainnet/nd-5 + /// // address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" + /// // index: 4 + /// // deposit: "10000000000000000" + /// // props: 29 + /// // timeout: 3600 + /// // registerTime: 1570109690 + /// // weight: 2000 + /// // proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" + /// } + /// } + /// + /// ``` + /// + public func nodes(limit: Int? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { + return execAndConvert(in3: in3, method: "in3_nodeList", params:limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), seed == nil ? RPCObject.none : RPCObject( seed! ), addresses == nil ? RPCObject.none : RPCObject( addresses! ), convertWith: { try NodeListDefinition($0,$1) } ) + } + + /// requests a signed blockhash from the node. + /// In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers + /// and the processising nodes will then aquire the signatures with this method from the other nodes. + /// + /// Since each node has a risk of signing a wrong blockhash and getting convicted and losing its deposit, + /// per default nodes will and should not sign blockHash of the last `minBlockHeight` (default: 6) blocks! + /// + /// - Parameter blocks : array of requested blocks. + /// - Returns: the Array with signatures of all the requires blocks. + /// + /// **Example** + /// + /// ```swift + /// NodelistAPI(in3).signBlockHash(blocks: NodelistBlocks(blockNumber: 8770580)) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // - blockHash: "0xd8189793f64567992eaadefc51834f3d787b03e9a6850b8b9b8003d8d84a76c8" + /// // block: 8770580 + /// // r: "0x954ed45416e97387a55b2231bff5dd72e822e4a5d60fa43bc9f9e49402019337" + /// // s: "0x277163f586585092d146d0d6885095c35c02b360e4125730c52332cf6b99e596" + /// // v: 28 + /// // msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" + /// } + /// } + /// + /// ``` + /// + public func signBlockHash(blocks: NodelistBlocks) -> Future { + return execAndConvert(in3: in3, method: "in3_sign", params:RPCObject( blocks.toRPCDict()), convertWith: { try NodelistSignBlockHash($0,$1) } ) + } + + /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. + /// - Parameter address : address of whitelist contract + /// - Returns: the whitelisted addresses + /// + /// **Example** + /// + /// ```swift + /// NodelistAPI(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = + /// // totalServers: 2 + /// // contract: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" + /// // lastBlockNumber: 1546354 + /// // nodes: + /// // - "0x1fe2e9bf29aa1938859af64c413361227d04059a" + /// // - "0x45d45e6ff99e6c34a235d263965910298985fcfe" + /// } + /// } + /// + /// ``` + /// + public func whitelist(address: String) -> Future { + return execAndConvert(in3: in3, method: "in3_whitelist", params:RPCObject( address), convertWith: { try NodelistWhitelist($0,$1) } ) + } + + +} +/// the current nodelist +public struct NodeListDefinition { + /// a array of node definitions. + public var nodes: [Node] + + /// the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. + public var contract: String + + /// the registryId (32 bytes) of the contract, which is there to verify the correct contract. + public var registryId: String + + /// the blockNumber of the last change of the list (usually the last event). + public var lastBlockNumber: UInt64 + + /// the total numbers of nodes. + public var totalServer: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + nodes = try toArray(obj["nodes"])!.map({ try Node($0,false)! }) + contract = try toString(obj["contract"],false)! + registryId = try toString(obj["registryId"],false)! + lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! + totalServer = try toUInt64(obj["totalServer"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["contract"] = RPCObject(contract) + obj["registryId"] = RPCObject(registryId) + obj["lastBlockNumber"] = RPCObject(lastBlockNumber) + obj["totalServer"] = RPCObject(totalServer) + return obj + } +} + +/// a array of node definitions. +public struct Node { + /// the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. + public var url: String + + /// the address of the signer + public var address: String + + /// the index within the nodeList of the contract + public var index: UInt64 + + /// the stored deposit + public var deposit: UInt256 + + /// the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) + public var props: String + + /// the time in seconds describing how long the deposit would be locked when trying to unregister a node. + public var timeout: UInt64 + + /// unix timestamp in seconds when the node has registered. + public var registerTime: UInt64 + + /// the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. + public var weight: UInt64 + + /// a hash value containing the above values. + /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof + /// per node instead of verifying each property as its own storage value. + /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` + /// + public var proofHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + url = try toString(obj["url"],false)! + address = try toString(obj["address"],false)! + index = try toUInt64(obj["index"],false)! + deposit = try toUInt256(obj["deposit"],false)! + props = try toString(obj["props"],false)! + timeout = try toUInt64(obj["timeout"],false)! + registerTime = try toUInt64(obj["registerTime"],false)! + weight = try toUInt64(obj["weight"],false)! + proofHash = try toString(obj["proofHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["url"] = RPCObject(url) + obj["address"] = RPCObject(address) + obj["index"] = RPCObject(index) + obj["deposit"] = RPCObject(deposit) + obj["props"] = RPCObject(props) + obj["timeout"] = RPCObject(timeout) + obj["registerTime"] = RPCObject(registerTime) + obj["weight"] = RPCObject(weight) + obj["proofHash"] = RPCObject(proofHash) + return obj + } +} + +/// array of requested blocks. +public struct NodelistBlocks { + /// the blockNumber to sign + public var blockNumber: UInt64 + + /// the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. + public var hash: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockNumber = try toUInt64(obj["blockNumber"],false)! + hash = try toString(obj["hash"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockNumber"] = RPCObject(blockNumber) + obj["hash"] = hash == nil ? RPCObject.none : RPCObject(hash!) + return obj + } +} + +/// the Array with signatures of all the requires blocks. +public struct NodelistSignBlockHash { + /// the blockhash which was signed. + public var blockHash: String + + /// the blocknumber + public var block: UInt64 + + /// r-value of the signature + public var r: String + + /// s-value of the signature + public var s: String + + /// v-value of the signature + public var v: String + + /// the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` + public var msgHash: String + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + blockHash = try toString(obj["blockHash"],false)! + block = try toUInt64(obj["block"],false)! + r = try toString(obj["r"],false)! + s = try toString(obj["s"],false)! + v = try toString(obj["v"],false)! + msgHash = try toString(obj["msgHash"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["blockHash"] = RPCObject(blockHash) + obj["block"] = RPCObject(block) + obj["r"] = RPCObject(r) + obj["s"] = RPCObject(s) + obj["v"] = RPCObject(v) + obj["msgHash"] = RPCObject(msgHash) + return obj + } +} + +/// the whitelisted addresses +public struct NodelistWhitelist { + /// array of whitelisted nodes addresses. + public var nodes: String + + /// the blockNumber of the last change of the in3 white list event. + public var lastWhiteList: UInt64 + + /// whitelist contract address. + public var contract: String + + /// the blockNumber of the last change of the list (usually the last event). + public var lastBlockNumber: UInt64 + + /// the total numbers of whitelist nodes. + public var totalServer: UInt64 + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + nodes = try toString(obj["nodes"],false)! + lastWhiteList = try toUInt64(obj["lastWhiteList"],false)! + contract = try toString(obj["contract"],false)! + lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! + totalServer = try toUInt64(obj["totalServer"],false)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["nodes"] = RPCObject(nodes) + obj["lastWhiteList"] = RPCObject(lastWhiteList) + obj["contract"] = RPCObject(contract) + obj["lastBlockNumber"] = RPCObject(lastBlockNumber) + obj["totalServer"] = RPCObject(totalServer) + return obj + } +} \ No newline at end of file diff --git a/swift/Sources/In3/API/Utils.swift b/swift/Sources/In3/API/Utils.swift new file mode 100644 index 000000000..0e8d4e973 --- /dev/null +++ b/swift/Sources/In3/API/Utils.swift @@ -0,0 +1,184 @@ +/// this is generated file don't edit it manually! + +import Foundation + +/// a Collection of utility-function. +/// +public class Utils { + internal var in3: In3 + + /// initialiazes the Utils API + /// - Parameter in3 : the incubed Client + init(_ in3: In3) { + self.in3 = in3 + } + + /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. + /// - Parameter signature : the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. + /// - Parameter params : a array of arguments. the number of arguments must match the arguments in the signature. + /// - Returns: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) + /// // result = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" + /// ``` + /// + public func abiEncode(signature: String, params: [AnyObject]) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_abiEncode", params:RPCObject( signature), RPCObject( params), convertWith: toString ) + } + + /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. + /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. + /// - Parameter data : the data to decode (usually the result of a eth_call) + /// - Returns: a array with the values after decodeing. + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") + /// // result = + /// // - "0x1234567890123456789012345678901234567890" + /// // - "0x05" + /// ``` + /// + public func abiDecode(signature: String, data: String) throws -> [RPCObject] { + return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), convertWith: { try toArray($0,$1)! } ) + } + + /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) + /// - Parameter address : the address to convert. + /// - Parameter useChainId : if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) + /// - Returns: the address-string using the upper/lowercase hex characters. + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) + /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" + /// ``` + /// + public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress", params:RPCObject( address), useChainId == nil ? RPCObject.none : RPCObject( useChainId! ), convertWith: toString ) + } + + /// converts the given value into wei. + /// - Parameter value : the value, which may be floating number as string + /// - Parameter unit : the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + /// - Returns: the value in wei as hex. + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).toWei(value: "20.0009123", unit: "eth") + /// // result = "0x01159183c4793db800" + /// ``` + /// + public func toWei(value: String, unit: String? = "eth") throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_toWei", params:RPCObject( value), unit == nil ? RPCObject.none : RPCObject( unit! ), convertWith: toString ) + } + + /// converts a given uint (also as hex) with a wei-value into a specified unit. + /// - Parameter value : the value in wei + /// - Parameter unit : the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` + /// - Parameter digits : fix number of digits after the comma. If left out, only as many as needed will be included. + /// - Returns: the value as string. + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) + /// // result = "0.158" + /// ``` + /// + public func fromWei(value: UInt256, unit: String, digits: Int? = nil) throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_fromWei", params:RPCObject( value), RPCObject( unit), digits == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", digits!) ), convertWith: toString ) + } + + /// clears the incubed cache (usually found in the .in3-folder) + /// - Returns: true indicating the success + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).cacheClear() + /// // result = true + /// ``` + /// + public func cacheClear() throws -> String { + return try execLocalAndConvert(in3: in3, method: "in3_cacheClear", convertWith: toString ) + } + + /// Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. + /// - Returns: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. + public func clientVersion() -> Future { + return execAndConvert(in3: in3, method: "web3_clientVersion", convertWith: toString ) + } + + /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. + /// + /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).keccak(data: "0x1234567890") + /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + /// ``` + /// + public func keccak(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "keccak", params:RPCObject( data), convertWith: toString ) + } + + /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. + /// + /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).sha3(data: "0x1234567890") + /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + /// ``` + /// + public func sha3(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "web3_sha3", params:RPCObject( data), convertWith: toString ) + } + + /// Returns sha-256 of the given data. + /// + /// No proof needed, since the client will execute this locally. + /// + /// - Parameter data : data to hash + /// - Returns: the 32byte hash of the data + /// + /// **Example** + /// + /// ```swift + /// let result = try UtilsAPI(in3).sha256(data: "0x1234567890") + /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + /// ``` + /// + public func sha256(data: String) throws -> String { + return try execLocalAndConvert(in3: in3, method: "sha256", params:RPCObject( data), convertWith: toString ) + } + + /// the Network Version (currently 1) + /// - Returns: the Version number + public func version() throws -> String { + return try execLocalAndConvert(in3: in3, method: "net_version", convertWith: toString ) + } + + +} diff --git a/swift/Sources/In3/API/ZksyncAPI.swift b/swift/Sources/In3/API/Zksync.swift similarity index 99% rename from swift/Sources/In3/API/ZksyncAPI.swift rename to swift/Sources/In3/API/Zksync.swift index fb8740ace..7812a1a72 100644 --- a/swift/Sources/In3/API/ZksyncAPI.swift +++ b/swift/Sources/In3/API/Zksync.swift @@ -10,7 +10,7 @@ import Foundation /// /// All zksync-methods can be used with `zksync_` or `zk_` prefix. /// -public class ZksyncAPI { +public class Zksync { internal var in3: In3 /// initialiazes the Zksync API @@ -859,4 +859,4 @@ public struct ZksyncLogs { obj["type"] = RPCObject(type) return obj } -} +} \ No newline at end of file diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift index 065116f48..280daecee 100644 --- a/swift/Sources/In3/In3.swift +++ b/swift/Sources/In3/In3.swift @@ -1,13 +1,16 @@ import CIn3 import Foundation -/// The I ncubed client +/// The Incubed client public class In3 { internal var in3: UnsafeMutablePointer? = nil /// the transport function public var transport: (_ url: String, _ method:String, _ payload:Data?, _ headers: [String], _ cb: @escaping (_ data:TransportResult)->Void) -> Void - - var cache: In3Cache? { + + /// set the cache impementation. + /// + /// the default is usually the FileCache storing data in the users home-directory, but by implementing the IN3Cache Protocol any custom storage is supported. + var cache: In3Cache? { get { return defaultCache } @@ -16,6 +19,7 @@ public class In3 { } } + /// initialize with a Configurations public init(_ config: In3Config) throws { transport = httpTransfer in3 = in3_for_chain_auto_init(1) @@ -27,6 +31,8 @@ public class In3 { in3_free(in3) } + /// change the configuration. + /// - Paramater config : the partial or full Configuration to change. public func configure(_ config: In3Config) throws { let jsonConfig = try JSONEncoder().encode(config) let error = in3_configure(in3, String(decoding: jsonConfig, as: UTF8.self)) @@ -58,10 +64,18 @@ public class In3 { } } + + /// executes a asnychronous request + /// + /// This requires a transport to be set + /// - Parameter method : the rpc-method to call + /// - Parameter params : the paramas as ROCPobjects + /// - Parameter cb : the callback which will be called with a Result (either success or error ) when done. public func exec(_ method: String, _ params: RPCObject..., cb: @escaping (_ result:RequestResult)->Void) throws { try In3Request(method,params,self,cb).exec() } - + + /// executes a json-rpc encoded request synchonously and returns the result as json-string public func executeJSON(_ rpc: String) -> String { return rpc.withCString { (baseAddress)->String in let count = rpc.utf8.count + 1 diff --git a/swift/Sources/In3/Utils/UInt256.swift b/swift/Sources/In3/Utils/UInt256.swift index ad75ba81a..d296f86ef 100644 --- a/swift/Sources/In3/Utils/UInt256.swift +++ b/swift/Sources/In3/Utils/UInt256.swift @@ -114,32 +114,41 @@ final public class UInt256: CustomStringConvertible, Hashable, Comparable, Decod return String(cString: buf).lowercased() } + /// String representation as decimals public var description: String { return toString(radix: 10) } + /// compare 2 UInt256 values + /// the result is zero if they are equal + /// negative if the current value is smaller than the given + /// positive if the current value is higher than the given public func compare(other: UInt256) -> Int32 { return mp_cmp(&self.value, &other.value) } - + + /// adds the given number and returns the sum of both public func add(_ val:UInt256) -> UInt256 { let res:UInt256 = UInt256() mp_add(&self.value, &val.value, &res.value) return res } + /// substracts the given number and returns the difference of both public func sub(_ val:UInt256) -> UInt256 { let res:UInt256 = UInt256() mp_sub(&self.value, &val.value, &res.value) return res } + /// multiplies the current with the given number and returns the product of both public func mul(_ val:UInt256) -> UInt256 { let res:UInt256 = UInt256() mp_mul(&self.value, &val.value, &res.value) return res } + /// divides the current number by the given and return the result public func div(_ val:UInt256) -> UInt256 { let res:UInt256 = UInt256() let mod:UInt256 = UInt256() @@ -147,13 +156,12 @@ final public class UInt256: CustomStringConvertible, Hashable, Comparable, Decod return res } + /// divides the current number by the given and return the rest or module operator public func mod(_ val:UInt256) -> UInt256 { let res:UInt256 = UInt256() mp_mod(&self.value, &val.value, &res.value) return res } - - } public func == (a: UInt256, b: UInt256) -> Bool { diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift index d69fcaf16..14555e4a7 100644 --- a/swift/Tests/In3Tests/In3Tests.swift +++ b/swift/Tests/In3Tests/In3Tests.swift @@ -79,7 +79,7 @@ final class In3Tests: XCTestCase { let expect = XCTestExpectation(description: "Should get a hash-value") // let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) let in3 = try In3(In3Config(chainId: "mainnet")) - let eth = EthAPI(in3) + let eth = Eth(in3) eth.getBlock().observe(using: { switch $0 { case let .failure(err): From 0d835c02a8cb593ba74108cfa4321bdc2181acd3 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 9 Apr 2021 21:46:04 +0200 Subject: [PATCH 113/221] generate initializer and added contract --- scripts/generator/swift.js | 13 +- swift/Sources/In3/API/Account.swift | 42 +++++ swift/Sources/In3/API/Btc.swift | 200 +++++++++++++++++++++++ swift/Sources/In3/API/Contract.swift | 107 ++++++++++++ swift/Sources/In3/API/Eth.swift | 224 +++++++++++++++++++++++++- swift/Sources/In3/API/Nodelist.swift | 78 +++++++++ swift/Sources/In3/API/Zksync.swift | 138 ++++++++++++++++ swift/Sources/In3/Utils/JsonRpc.swift | 19 +++ 8 files changed, 815 insertions(+), 6 deletions(-) create mode 100644 swift/Sources/In3/API/Contract.swift diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 558d9c80f..4f9a9f2d2 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -50,6 +50,9 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api let toRPC = '\n internal func toRPCDict() -> [String:RPCObject] {\n var obj:[String:RPCObject] = [:]' let init = ' internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws {' + '\n guard let obj = try toObject(rpc, optional) else { return nil }' + let pubInitHead = ' public init(' + let pubInitBody = '' + let pubInitDescr = '\n /// initialize the ' + swiftType + '\n ///' for (let name of Object.keys(conf)) { @@ -57,6 +60,9 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api const t = getAPIType(p, typeConfigs, typesGenerated, name, api) content.push(' /// ' + (p.descr || ('the ' + camelCaseUp(name))).split('\n').join('\n /// ')) content.push(' public var ' + name + ': ' + t + '\n') + pubInitHead += (pubInitHead.endsWith('(') ? '' : ', ') + name + ': ' + t + (t.endsWith('?') ? ' = nil' : '') + pubInitDescr += '\n /// - Parameter ' + name + ' : ' + (p.descr || ('the ' + camelCaseUp(name))).split('\n').join('\n /// ') + pubInitBody += '\n self.' + name + ' = ' + name if (p.array) { if (p.optional) { init += '\n if let ' + name + ' = try toArray(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ') {' @@ -87,7 +93,10 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api } - typesGenerated[swiftType] = content.join('\n') + '\n' + init + '\n }\n' + (toRPC.indexOf('obj["') == -1 ? '' : (toRPC + '\n return obj\n }')) + '\n}' + typesGenerated[swiftType] = content.join('\n') + '\n' + init + '\n }\n' + (toRPC.indexOf('obj["') == -1 ? '' : (toRPC + '\n return obj\n }')) + + pubInitDescr + '\n' + + pubInitHead + ') {' + + pubInitBody + '\n }\n}' } function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { @@ -242,7 +251,7 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc if (p.fixed === undefined) { if (!s.endsWith('(')) s += ', ' content.push(' /// - Parameter ' + name + ' : ' + (p.descr || name).split('\n').join(' /// ')) - s += name + ': ' + type + (p.optional || p.default !== undefined ? ' = ' + (p.default !== undefined ? JSON.stringify(p.default) : 'nil') : '') + s += name + ': ' + type + (p.optional || p.optionalAPI || p.default !== undefined ? ' = ' + (p.default !== undefined ? JSON.stringify(p.default) : 'nil') : '') } // add the param to the rpc call params += (params ? ' ' : ' params:') + toParam(name, p, types) + ',' diff --git a/swift/Sources/In3/API/Account.swift b/swift/Sources/In3/API/Account.swift index ced37b033..02ab53870 100644 --- a/swift/Sources/In3/API/Account.swift +++ b/swift/Sources/In3/API/Account.swift @@ -296,6 +296,14 @@ public struct AccountEcrecover { obj["address"] = RPCObject(address) return obj } + /// initialize the AccountEcrecover + /// + /// - Parameter publicKey : the public Key of the signer (64 bytes) + /// - Parameter address : the address + public init(publicKey: String, address: String) { + self.publicKey = publicKey + self.address = address + } } /// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). @@ -343,6 +351,24 @@ public struct AccountTransaction { obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) return obj } + /// initialize the AccountTransaction + /// + /// - Parameter to : receipient of the transaction. + /// - Parameter from : sender of the address (if not sepcified, the first signer will be the sender) + /// - Parameter value : value in wei to send + /// - Parameter gas : the gas to be send along + /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + /// - Parameter data : the data-section of the transaction + public init(to: String, from: String, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { + self.to = to + self.from = from + self.value = value + self.gas = gas + self.gasPrice = gasPrice + self.nonce = nonce + self.data = data + } } /// the signature @@ -385,4 +411,20 @@ public struct AccountSignData { obj["v"] = RPCObject(v) return obj } + /// initialize the AccountSignData + /// + /// - Parameter message : original message used + /// - Parameter messageHash : the hash the signature is based on + /// - Parameter signature : the signature (65 bytes) + /// - Parameter r : the x-value of the EC-Point + /// - Parameter s : the y-value of the EC-Point + /// - Parameter v : the recovery value (0|1) + 27 + public init(message: String, messageHash: String, signature: String, r: String, s: String, v: String) { + self.message = message + self.messageHash = messageHash + self.signature = signature + self.r = r + self.s = s + self.v = v + } } \ No newline at end of file diff --git a/swift/Sources/In3/API/Btc.swift b/swift/Sources/In3/API/Btc.swift index 2c65bb4a8..a72195544 100644 --- a/swift/Sources/In3/API/Btc.swift +++ b/swift/Sources/In3/API/Btc.swift @@ -523,6 +523,40 @@ public struct Btcblockheader { obj["nextblockhash"] = RPCObject(nextblockhash) return obj } + /// initialize the Btcblockheader + /// + /// - Parameter hash : the block hash (same as provided) + /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain + /// - Parameter height : The block height or index + /// - Parameter version : The block version + /// - Parameter versionHex : The block version formatted in hexadecimal + /// - Parameter merkleroot : The merkle root ( 32 bytes ) + /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter nonce : The nonce + /// - Parameter bits : The bits ( 4 bytes as hex) representing the target + /// - Parameter difficulty : The difficulty + /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) + /// - Parameter nTx : The number of transactions in the block. + /// - Parameter previousblockhash : The hash of the previous block + /// - Parameter nextblockhash : The hash of the next block + public init(hash: String, confirmations: Int, height: UInt64, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, previousblockhash: String, nextblockhash: String) { + self.hash = hash + self.confirmations = confirmations + self.height = height + self.version = version + self.versionHex = versionHex + self.merkleroot = merkleroot + self.time = time + self.mediantime = mediantime + self.nonce = nonce + self.bits = bits + self.difficulty = difficulty + self.chainwork = chainwork + self.nTx = nTx + self.previousblockhash = previousblockhash + self.nextblockhash = nextblockhash + } } /// the block. @@ -617,6 +651,42 @@ public struct Btcblock { obj["nextblockhash"] = RPCObject(nextblockhash) return obj } + /// initialize the Btcblock + /// + /// - Parameter hash : the block hash (same as provided) + /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain + /// - Parameter height : The block height or index + /// - Parameter version : The block version + /// - Parameter versionHex : The block version formatted in hexadecimal + /// - Parameter merkleroot : The merkle root ( 32 bytes ) + /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter nonce : The nonce + /// - Parameter bits : The bits ( 4 bytes as hex) representing the target + /// - Parameter difficulty : The difficulty + /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) + /// - Parameter nTx : The number of transactions in the block. + /// - Parameter tx : the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + /// - Parameter previousblockhash : The hash of the previous block + /// - Parameter nextblockhash : The hash of the next block + public init(hash: String, confirmations: Int, height: UInt256, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, tx: [String], previousblockhash: String, nextblockhash: String) { + self.hash = hash + self.confirmations = confirmations + self.height = height + self.version = version + self.versionHex = versionHex + self.merkleroot = merkleroot + self.time = time + self.mediantime = mediantime + self.nonce = nonce + self.bits = bits + self.difficulty = difficulty + self.chainwork = chainwork + self.nTx = nTx + self.tx = tx + self.previousblockhash = previousblockhash + self.nextblockhash = nextblockhash + } } /// the block. @@ -711,6 +781,42 @@ public struct BtcblockWithTx { obj["nextblockhash"] = RPCObject(nextblockhash) return obj } + /// initialize the BtcblockWithTx + /// + /// - Parameter hash : the block hash (same as provided) + /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain + /// - Parameter height : The block height or index + /// - Parameter version : The block version + /// - Parameter versionHex : The block version formatted in hexadecimal + /// - Parameter merkleroot : The merkle root ( 32 bytes ) + /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter nonce : The nonce + /// - Parameter bits : The bits ( 4 bytes as hex) representing the target + /// - Parameter difficulty : The difficulty + /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) + /// - Parameter nTx : The number of transactions in the block. + /// - Parameter tx : the array of transactions either as ids (verbose=1) or full transaction (verbose=2) + /// - Parameter previousblockhash : The hash of the previous block + /// - Parameter nextblockhash : The hash of the next block + public init(hash: String, confirmations: Int, height: UInt64, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, tx: [Btctransaction], previousblockhash: String, nextblockhash: String) { + self.hash = hash + self.confirmations = confirmations + self.height = height + self.version = version + self.versionHex = versionHex + self.merkleroot = merkleroot + self.time = time + self.mediantime = mediantime + self.nonce = nonce + self.bits = bits + self.difficulty = difficulty + self.chainwork = chainwork + self.nTx = nTx + self.tx = tx + self.previousblockhash = previousblockhash + self.nextblockhash = nextblockhash + } } /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) @@ -796,6 +902,40 @@ public struct Btctransaction { obj["time"] = RPCObject(time) return obj } + /// initialize the Btctransaction + /// + /// - Parameter txid : txid + /// - Parameter in_active_chain : Whether specified block is in the active chain or not (only present with explicit "blockhash" argument) + /// - Parameter hex : The serialized, hex-encoded data for `txid` + /// - Parameter hash : The transaction hash (differs from txid for witness transactions) + /// - Parameter size : The serialized transaction size + /// - Parameter vsize : The virtual transaction size (differs from size for witness transactions) + /// - Parameter weight : The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) + /// - Parameter version : The version + /// - Parameter locktime : The lock time + /// - Parameter vin : array of json objects of incoming txs to be used + /// - Parameter vout : array of json objects describing the tx outputs + /// - Parameter blockhash : the block hash + /// - Parameter confirmations : The confirmations + /// - Parameter blocktime : The block time in seconds since epoch (Jan 1 1970 GMT) + /// - Parameter time : Same as "blocktime" + public init(txid: String, in_active_chain: Bool, hex: String, hash: String, size: UInt64, vsize: UInt64, weight: UInt64, version: Int, locktime: UInt64, vin: [BtcVin], vout: [BtcVout], blockhash: String, confirmations: Int, blocktime: UInt64, time: UInt64) { + self.txid = txid + self.in_active_chain = in_active_chain + self.hex = hex + self.hash = hash + self.size = size + self.vsize = vsize + self.weight = weight + self.version = version + self.locktime = locktime + self.vin = vin + self.vout = vout + self.blockhash = blockhash + self.confirmations = confirmations + self.blocktime = blocktime + self.time = time + } } /// array of json objects of incoming txs to be used @@ -831,6 +971,20 @@ public struct BtcVin { obj["sequence"] = RPCObject(sequence) return obj } + /// initialize the BtcVin + /// + /// - Parameter txid : the transaction id + /// - Parameter vout : the index of the transaction out to be used + /// - Parameter scriptSig : the script + /// - Parameter sequence : The script sequence number + /// - Parameter txinwitness : hex-encoded witness data (if any) + public init(txid: String, vout: UInt64, scriptSig: BtcScriptSig, sequence: UInt64, txinwitness: [String]) { + self.txid = txid + self.vout = vout + self.scriptSig = scriptSig + self.sequence = sequence + self.txinwitness = txinwitness + } } /// the script @@ -853,6 +1007,14 @@ public struct BtcScriptSig { obj["hex"] = RPCObject(hex) return obj } + /// initialize the BtcScriptSig + /// + /// - Parameter asm : the asm-codes + /// - Parameter hex : hex representation + public init(asm: String, hex: String) { + self.asm = asm + self.hex = hex + } } /// array of json objects describing the tx outputs @@ -879,6 +1041,16 @@ public struct BtcVout { obj["n"] = RPCObject(n) return obj } + /// initialize the BtcVout + /// + /// - Parameter value : The Value in BTC + /// - Parameter n : the index + /// - Parameter scriptPubKey : the script pubkey + public init(value: Double, n: Int, scriptPubKey: BtcScriptPubKey) { + self.value = value + self.n = n + self.scriptPubKey = scriptPubKey + } } /// the script pubkey @@ -915,6 +1087,20 @@ public struct BtcScriptPubKey { obj["type"] = RPCObject(type) return obj } + /// initialize the BtcScriptPubKey + /// + /// - Parameter asm : asm + /// - Parameter hex : hex representation of the script + /// - Parameter reqSigs : the required signatures + /// - Parameter type : The type, eg 'pubkeyhash' + /// - Parameter addresses : Array of address(each representing a bitcoin adress) + public init(asm: String, hex: String, reqSigs: Int, type: String, addresses: [String]) { + self.asm = asm + self.hex = hex + self.reqSigs = reqSigs + self.type = type + self.addresses = addresses + } } /// A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. @@ -952,4 +1138,18 @@ public struct BtcProofTarget { obj["cbtxMerkleProof"] = RPCObject(cbtxMerkleProof) return obj } + /// initialize the BtcProofTarget + /// + /// - Parameter dap : the difficulty adjustement period + /// - Parameter block : the first blockheader + /// - Parameter final : the finality header + /// - Parameter cbtx : the coinbase transaction as hex + /// - Parameter cbtxMerkleProof : the coinbasetx merkle proof + public init(dap: UInt64, block: String, final: String, cbtx: String, cbtxMerkleProof: String) { + self.dap = dap + self.block = block + self.final = final + self.cbtx = cbtx + self.cbtxMerkleProof = cbtxMerkleProof + } } \ No newline at end of file diff --git a/swift/Sources/In3/API/Contract.swift b/swift/Sources/In3/API/Contract.swift new file mode 100644 index 000000000..390e9d9e7 --- /dev/null +++ b/swift/Sources/In3/API/Contract.swift @@ -0,0 +1,107 @@ +// +// File.swift +// +// +// Created by Simon Jentzsch on 09.04.21. +// + +import Foundation + +public class Contract { + + var in3:In3 + var address:String? + var abi:[ABI] + + public init(in3:In3, abi:[ABI], at: String?=nil) throws { + self.in3=in3 + self.abi=abi + self.address = at + } + + + public func deploy(data: String, args: [AnyObject]) { + } + + public func call(name: String, args: [AnyObject]) -> Future<[Any]> { + let p = Promise<[Any]>() + guard let adr = address, let def = self[name] else { + p.reject(with: IncubedError.config(message: "The Contract has no address!")) + return p + } + do { + let data = try encodeCall(name: name, args: args) + return Eth(in3).call(tx: EthTx(to: adr, data: data)).chained(using: { + let res = try Utils(self.in3).abiDecode(signature: def.signature, data : $0) + return Promise(value: res.map({ $0.asObject() }) as [Any]) + }) + } catch { + p.reject(with: error) + return p + } + } + + /// returns the abi encoded arguments as hex string + public func encodeCall(name: String, args: [AnyObject]) throws -> String{ + if let abi = self[name] { + return try Utils(in3).abiEncode(signature: abi.signature, params: args) + } else { + throw IncubedError.rpc(message: "The method \(name) does not exist in the contract!") + } + } + + subscript(name: String) -> ABI? { + get { + return self.abi.first(where:{ $0.name == name }) + } + } +} + + + +/// a function, event or a +public struct ABI : Codable { + public var hash:String? + public var anonymous: Bool? + public var constant: Bool? + public var payable: Bool? + public var stateMutability: String? + public var components: [ABIField]? + public var inputs: [ABIField]? + public var outputs: [ABIField]? + public var name: String? + public var type: String + public var internalType: String? + public var signature:String { + guard let inp = inputs, let name = self.name else { + return "\(self.name ?? "_")()" + } + var sig = "\(name)(\( inp.map({ $0.signature }).joined(separator: ",") ))" + if let r = outputs { + sig += ":(\( r.map({ $0.signature }).joined(separator: ",") ))" + } + return sig + } +} + + +/// configure the Bitcoin verification +public struct ABIField : Codable { + public var internalType: String? + public var components: [ABIField]? + public var indexed: Bool? + public var name: String + public var type: String + public var signature:String { + let parts = type.split(separator: "[", maxSplits: 2) + var baseType = String(parts[0]) + let array = parts.count == 2 ? String(parts[1]) : "" + + if baseType == "tuple", let cs = components { + baseType = "(\(cs.map({ $0.signature }).joined(separator: ",")))" + } + return baseType + array + } +} + + diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift index 6c2e8f448..34a5c18c9 100644 --- a/swift/Sources/In3/API/Eth.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -448,7 +448,7 @@ public class Eth { /// /// ``` /// - public func getBalance(account: String, block: UInt64?) -> Future { + public func getBalance(account: String, block: UInt64? = nil) -> Future { return execAndConvert(in3: in3, method: "eth_getBalance", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } @@ -472,7 +472,7 @@ public class Eth { /// /// ``` /// - public func getTransactionCount(account: String, block: UInt64?) -> Future { + public func getTransactionCount(account: String, block: UInt64? = nil) -> Future { return execAndConvert(in3: in3, method: "eth_getTransactionCount", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } @@ -550,7 +550,7 @@ public class Eth { /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). /// - Parameter block : the blockNumber or `latest` /// - Returns: the amount of gass needed. - public func estimateGas(tx: EthTransaction, block: UInt64?) -> Future { + public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { return execAndConvert(in3: in3, method: "eth_estimateGas", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } @@ -574,7 +574,7 @@ public class Eth { /// /// ``` /// - public func call(tx: EthTx, block: UInt64?) -> Future { + public func call(tx: EthTx, block: UInt64? = nil) -> Future { return execAndConvert(in3: in3, method: "eth_call", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } @@ -731,6 +731,48 @@ public struct EthBlockdataWithTxHashes { obj["timestamp"] = RPCObject(timestamp) return obj } + /// initialize the EthBlockdataWithTxHashes + /// + /// - Parameter transactions : Array of transaction hashes + /// - Parameter number : the block number. `null` when its pending block. + /// - Parameter hash : hash of the block. `null` when its pending block. + /// - Parameter parentHash : hash of the parent block. + /// - Parameter nonce : hash of the generated proof-of-work. `null` when its pending block. + /// - Parameter sha3Uncles : SHA3 of the uncles Merkle root in the block. + /// - Parameter logsBloom : the bloom filter for the logs of the block. `null` when its pending block. + /// - Parameter transactionsRoot : the root of the transaction trie of the block. + /// - Parameter stateRoot : the root of the final state trie of the block. + /// - Parameter receiptsRoot : the root of the receipts trie of the block. + /// - Parameter miner : the address of the beneficiary to whom the mining rewards were given. + /// - Parameter difficulty : integer of the difficulty for this block. + /// - Parameter totalDifficulty : integer of the total difficulty of the chain until this block. + /// - Parameter extraData : the "extra data" field of this block. + /// - Parameter size : integer the size of this block in bytes. + /// - Parameter gasLimit : the maximum gas allowed in this block. + /// - Parameter gasUsed : the total used gas by all transactions in this block. + /// - Parameter timestamp : the unix timestamp for when the block was collated. + /// - Parameter uncles : Array of uncle hashes. + public init(transactions: [String], number: UInt64, hash: String, parentHash: String, nonce: UInt256, sha3Uncles: String, logsBloom: String, transactionsRoot: String, stateRoot: String, receiptsRoot: String, miner: String, difficulty: UInt256, totalDifficulty: UInt256, extraData: String, size: UInt64, gasLimit: UInt64, gasUsed: UInt64, timestamp: UInt64, uncles: [String]) { + self.transactions = transactions + self.number = number + self.hash = hash + self.parentHash = parentHash + self.nonce = nonce + self.sha3Uncles = sha3Uncles + self.logsBloom = logsBloom + self.transactionsRoot = transactionsRoot + self.stateRoot = stateRoot + self.receiptsRoot = receiptsRoot + self.miner = miner + self.difficulty = difficulty + self.totalDifficulty = totalDifficulty + self.extraData = extraData + self.size = size + self.gasLimit = gasLimit + self.gasUsed = gasUsed + self.timestamp = timestamp + self.uncles = uncles + } } /// the blockdata, or in case the block with that number does not exist, `null` will be returned. @@ -836,6 +878,48 @@ public struct EthBlockdata { obj["timestamp"] = RPCObject(timestamp) return obj } + /// initialize the EthBlockdata + /// + /// - Parameter transactions : Array of transaction objects + /// - Parameter number : the block number. `null` when its pending block. + /// - Parameter hash : hash of the block. `null` when its pending block. + /// - Parameter parentHash : hash of the parent block. + /// - Parameter nonce : hash of the generated proof-of-work. `null` when its pending block. + /// - Parameter sha3Uncles : SHA3 of the uncles Merkle root in the block. + /// - Parameter logsBloom : the bloom filter for the logs of the block. `null` when its pending block. + /// - Parameter transactionsRoot : the root of the transaction trie of the block. + /// - Parameter stateRoot : the root of the final state trie of the block. + /// - Parameter receiptsRoot : the root of the receipts trie of the block. + /// - Parameter miner : the address of the beneficiary to whom the mining rewards were given. + /// - Parameter difficulty : integer of the difficulty for this block. + /// - Parameter totalDifficulty : integer of the total difficulty of the chain until this block. + /// - Parameter extraData : the "extra data" field of this block. + /// - Parameter size : integer the size of this block in bytes. + /// - Parameter gasLimit : the maximum gas allowed in this block. + /// - Parameter gasUsed : the total used gas by all transactions in this block. + /// - Parameter timestamp : the unix timestamp for when the block was collated. + /// - Parameter uncles : Array of uncle hashes. + public init(transactions: [EthTransactiondata], number: UInt64, hash: String, parentHash: String, nonce: UInt256, sha3Uncles: String, logsBloom: String, transactionsRoot: String, stateRoot: String, receiptsRoot: String, miner: String, difficulty: UInt256, totalDifficulty: UInt256, extraData: String, size: UInt64, gasLimit: UInt64, gasUsed: UInt64, timestamp: UInt64, uncles: [String]) { + self.transactions = transactions + self.number = number + self.hash = hash + self.parentHash = parentHash + self.nonce = nonce + self.sha3Uncles = sha3Uncles + self.logsBloom = logsBloom + self.transactionsRoot = transactionsRoot + self.stateRoot = stateRoot + self.receiptsRoot = receiptsRoot + self.miner = miner + self.difficulty = difficulty + self.totalDifficulty = totalDifficulty + self.extraData = extraData + self.size = size + self.gasLimit = gasLimit + self.gasUsed = gasUsed + self.timestamp = timestamp + self.uncles = uncles + } } /// Array of transaction objects @@ -918,6 +1002,38 @@ public struct EthTransactiondata { obj["s"] = RPCObject(s) return obj } + /// initialize the EthTransactiondata + /// + /// - Parameter to : receipient of the transaction. + /// - Parameter from : sender or signer of the transaction + /// - Parameter value : value in wei to send + /// - Parameter gas : the gas to be send along + /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + /// - Parameter blockHash : blockHash of the block holding this transaction or `null` if still pending. + /// - Parameter blockNumber : blockNumber of the block holding this transaction or `null` if still pending. + /// - Parameter hash : transactionHash + /// - Parameter input : data of the transaaction + /// - Parameter transactionIndex : index of the transaaction in the block + /// - Parameter v : recovery-byte of the signature + /// - Parameter r : x-value of the EC-Point of the signature + /// - Parameter s : y-value of the EC-Point of the signature + public init(to: String, from: String, value: UInt256, gas: UInt64, gasPrice: UInt64, nonce: UInt64, blockHash: String, blockNumber: UInt64, hash: String, input: String, transactionIndex: UInt64, v: String, r: String, s: String) { + self.to = to + self.from = from + self.value = value + self.gas = gas + self.gasPrice = gasPrice + self.nonce = nonce + self.blockHash = blockHash + self.blockNumber = blockNumber + self.hash = hash + self.input = input + self.transactionIndex = transactionIndex + self.v = v + self.r = r + self.s = s + } } /// The filter criteria for the events. @@ -958,6 +1074,20 @@ public struct EthFilter { obj["blockhash"] = blockhash == nil ? RPCObject.none : RPCObject(blockhash!) return obj } + /// initialize the EthFilter + /// + /// - Parameter fromBlock : Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + /// - Parameter toBlock : Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. + /// - Parameter address : Contract address or a list of addresses from which logs should originate. + /// - Parameter topics : Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. + /// - Parameter blockhash : With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. + public init(fromBlock: UInt64? = nil, toBlock: UInt64? = nil, address: String? = nil, topics: [String]? = nil, blockhash: String? = nil) { + self.fromBlock = fromBlock + self.toBlock = toBlock + self.address = address + self.topics = topics + self.blockhash = blockhash + } } /// the transactiondata to send @@ -1005,6 +1135,24 @@ public struct EthTransaction { obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) return obj } + /// initialize the EthTransaction + /// + /// - Parameter to : receipient of the transaction. + /// - Parameter from : sender of the address (if not sepcified, the first signer will be the sender) + /// - Parameter value : value in wei to send + /// - Parameter gas : the gas to be send along + /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + /// - Parameter data : the data-section of the transaction + public init(to: String, from: String, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { + self.to = to + self.from = from + self.value = value + self.gas = gas + self.gasPrice = gasPrice + self.nonce = nonce + self.data = data + } } /// the transactionReceipt @@ -1066,6 +1214,30 @@ public struct EthTransactionReceipt { obj["transactionIndex"] = RPCObject(transactionIndex) return obj } + /// initialize the EthTransactionReceipt + /// + /// - Parameter blockNumber : the blockNumber + /// - Parameter blockHash : blockhash if ther containing block + /// - Parameter contractAddress : the deployed contract in case the tx did deploy a new contract + /// - Parameter cumulativeGasUsed : gas used for all transaction up to this one in the block + /// - Parameter gasUsed : gas used by this transaction. + /// - Parameter logs : array of events created during execution of the tx + /// - Parameter logsBloom : bloomfilter used to detect events for `eth_getLogs` + /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure + /// - Parameter transactionHash : requested transactionHash + /// - Parameter transactionIndex : transactionIndex within the containing block. + public init(blockNumber: UInt64, blockHash: String, contractAddress: String, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: EthLogs, logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { + self.blockNumber = blockNumber + self.blockHash = blockHash + self.contractAddress = contractAddress + self.cumulativeGasUsed = cumulativeGasUsed + self.gasUsed = gasUsed + self.logs = logs + self.logsBloom = logsBloom + self.status = status + self.transactionHash = transactionHash + self.transactionIndex = transactionIndex + } } /// array of events created during execution of the tx @@ -1132,6 +1304,32 @@ public struct EthLogs { obj["type"] = RPCObject(type) return obj } + /// initialize the EthLogs + /// + /// - Parameter address : the address triggering the event. + /// - Parameter blockNumber : the blockNumber + /// - Parameter blockHash : blockhash if ther containing block + /// - Parameter data : abi-encoded data of the event (all non indexed fields) + /// - Parameter logIndex : the index of the even within the block. + /// - Parameter removed : the reorg-status of the event. + /// - Parameter topics : array of 32byte-topics of the indexed fields. + /// - Parameter transactionHash : requested transactionHash + /// - Parameter transactionIndex : transactionIndex within the containing block. + /// - Parameter transactionLogIndex : index of the event within the transaction. + /// - Parameter type : mining-status + public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int, type: String) { + self.address = address + self.blockNumber = blockNumber + self.blockHash = blockHash + self.data = data + self.logIndex = logIndex + self.removed = removed + self.topics = topics + self.transactionHash = transactionHash + self.transactionIndex = transactionIndex + self.transactionLogIndex = transactionLogIndex + self.type = type + } } /// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). @@ -1179,4 +1377,22 @@ public struct EthTx { obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) return obj } + /// initialize the EthTx + /// + /// - Parameter to : address of the contract + /// - Parameter from : sender of the address + /// - Parameter value : value in wei to send + /// - Parameter gas : the gas to be send along + /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + /// - Parameter data : the data-section of the transaction, which includes the functionhash and the abi-encoded arguments + public init(to: String, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { + self.to = to + self.from = from + self.value = value + self.gas = gas + self.gasPrice = gasPrice + self.nonce = nonce + self.data = data + } } \ No newline at end of file diff --git a/swift/Sources/In3/API/Nodelist.swift b/swift/Sources/In3/API/Nodelist.swift index 73b309593..9b823613c 100644 --- a/swift/Sources/In3/API/Nodelist.swift +++ b/swift/Sources/In3/API/Nodelist.swift @@ -160,6 +160,20 @@ public struct NodeListDefinition { obj["totalServer"] = RPCObject(totalServer) return obj } + /// initialize the NodeListDefinition + /// + /// - Parameter nodes : a array of node definitions. + /// - Parameter contract : the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. + /// - Parameter registryId : the registryId (32 bytes) of the contract, which is there to verify the correct contract. + /// - Parameter lastBlockNumber : the blockNumber of the last change of the list (usually the last event). + /// - Parameter totalServer : the total numbers of nodes. + public init(nodes: [Node], contract: String, registryId: String, lastBlockNumber: UInt64, totalServer: UInt64) { + self.nodes = nodes + self.contract = contract + self.registryId = registryId + self.lastBlockNumber = lastBlockNumber + self.totalServer = totalServer + } } /// a array of node definitions. @@ -221,6 +235,32 @@ public struct Node { obj["proofHash"] = RPCObject(proofHash) return obj } + /// initialize the Node + /// + /// - Parameter url : the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. + /// - Parameter address : the address of the signer + /// - Parameter index : the index within the nodeList of the contract + /// - Parameter deposit : the stored deposit + /// - Parameter props : the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) + /// - Parameter timeout : the time in seconds describing how long the deposit would be locked when trying to unregister a node. + /// - Parameter registerTime : unix timestamp in seconds when the node has registered. + /// - Parameter weight : the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. + /// - Parameter proofHash : a hash value containing the above values. + /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof + /// per node instead of verifying each property as its own storage value. + /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` + /// + public init(url: String, address: String, index: UInt64, deposit: UInt256, props: String, timeout: UInt64, registerTime: UInt64, weight: UInt64, proofHash: String) { + self.url = url + self.address = address + self.index = index + self.deposit = deposit + self.props = props + self.timeout = timeout + self.registerTime = registerTime + self.weight = weight + self.proofHash = proofHash + } } /// array of requested blocks. @@ -243,6 +283,14 @@ public struct NodelistBlocks { obj["hash"] = hash == nil ? RPCObject.none : RPCObject(hash!) return obj } + /// initialize the NodelistBlocks + /// + /// - Parameter blockNumber : the blockNumber to sign + /// - Parameter hash : the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. + public init(blockNumber: UInt64, hash: String? = nil) { + self.blockNumber = blockNumber + self.hash = hash + } } /// the Array with signatures of all the requires blocks. @@ -285,6 +333,22 @@ public struct NodelistSignBlockHash { obj["msgHash"] = RPCObject(msgHash) return obj } + /// initialize the NodelistSignBlockHash + /// + /// - Parameter blockHash : the blockhash which was signed. + /// - Parameter block : the blocknumber + /// - Parameter r : r-value of the signature + /// - Parameter s : s-value of the signature + /// - Parameter v : v-value of the signature + /// - Parameter msgHash : the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` + public init(blockHash: String, block: UInt64, r: String, s: String, v: String, msgHash: String) { + self.blockHash = blockHash + self.block = block + self.r = r + self.s = s + self.v = v + self.msgHash = msgHash + } } /// the whitelisted addresses @@ -322,4 +386,18 @@ public struct NodelistWhitelist { obj["totalServer"] = RPCObject(totalServer) return obj } + /// initialize the NodelistWhitelist + /// + /// - Parameter nodes : array of whitelisted nodes addresses. + /// - Parameter lastWhiteList : the blockNumber of the last change of the in3 white list event. + /// - Parameter contract : whitelist contract address. + /// - Parameter lastBlockNumber : the blockNumber of the last change of the list (usually the last event). + /// - Parameter totalServer : the total numbers of whitelist nodes. + public init(nodes: String, lastWhiteList: UInt64, contract: String, lastBlockNumber: UInt64, totalServer: UInt64) { + self.nodes = nodes + self.lastWhiteList = lastWhiteList + self.contract = contract + self.lastBlockNumber = lastBlockNumber + self.totalServer = totalServer + } } \ No newline at end of file diff --git a/swift/Sources/In3/API/Zksync.swift b/swift/Sources/In3/API/Zksync.swift index 7812a1a72..f01955c42 100644 --- a/swift/Sources/In3/API/Zksync.swift +++ b/swift/Sources/In3/API/Zksync.swift @@ -528,6 +528,14 @@ public struct ZksyncContractAddress { obj["mainContract"] = RPCObject(mainContract) return obj } + /// initialize the ZksyncContractAddress + /// + /// - Parameter govContract : the address of the govement contract + /// - Parameter mainContract : the address of the main contract + public init(govContract: String, mainContract: String) { + self.govContract = govContract + self.mainContract = mainContract + } } /// a array of tokens-definitions. This request also caches them and will return the results from cahe if available. @@ -560,6 +568,18 @@ public struct ZksyncTokens { obj["symbol"] = RPCObject(symbol) return obj } + /// initialize the ZksyncTokens + /// + /// - Parameter address : the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) + /// - Parameter decimals : decimals to be used when formating it for human readable representation. + /// - Parameter id : id which will be used when encoding the token. + /// - Parameter symbol : symbol for the token + public init(address: String, decimals: Int, id: UInt64, symbol: String) { + self.address = address + self.decimals = decimals + self.id = id + self.symbol = symbol + } } /// the current state of the requested account. @@ -594,6 +614,20 @@ public struct ZksyncAccountInfo { obj["id"] = RPCObject(id) return obj } + /// initialize the ZksyncAccountInfo + /// + /// - Parameter address : the address of the account + /// - Parameter commited : the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. + /// - Parameter depositing : the state of all depositing-tx. + /// - Parameter id : the assigned id of the account, which will be used when encoding it into the rollup. + /// - Parameter verified : the state after the rollup was verified in L1. + public init(address: String, commited: ZksyncCommited, depositing: ZksyncDepositing, id: UInt64, verified: ZksyncVerified) { + self.address = address + self.commited = commited + self.depositing = depositing + self.id = id + self.verified = verified + } } /// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. @@ -620,6 +654,16 @@ public struct ZksyncCommited { obj["pubKeyHash"] = RPCObject(pubKeyHash) return obj } + /// initialize the ZksyncCommited + /// + /// - Parameter balances : the token-balance + /// - Parameter nonce : the nonce or transaction count. + /// - Parameter pubKeyHash : the pubKeyHash set for the requested account or `0x0000...` if not set yet. + public init(balances: [String:UInt256], nonce: UInt64, pubKeyHash: String) { + self.balances = balances + self.nonce = nonce + self.pubKeyHash = pubKeyHash + } } /// the state of all depositing-tx. @@ -632,6 +676,12 @@ public struct ZksyncDepositing { balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) } + /// initialize the ZksyncDepositing + /// + /// - Parameter balances : the token-values. + public init(balances: [String:UInt256]) { + self.balances = balances + } } /// the state after the rollup was verified in L1. @@ -658,6 +708,16 @@ public struct ZksyncVerified { obj["pubKeyHash"] = RPCObject(pubKeyHash) return obj } + /// initialize the ZksyncVerified + /// + /// - Parameter balances : the token-balances. + /// - Parameter nonce : the nonce or transaction count. + /// - Parameter pubKeyHash : the pubKeyHash set for the requested account or `0x0000...` if not set yet. + public init(balances: [String:UInt256], nonce: UInt64, pubKeyHash: String) { + self.balances = balances + self.nonce = nonce + self.pubKeyHash = pubKeyHash + } } /// the current state of the requested tx. @@ -690,6 +750,18 @@ public struct ZksyncTxInfo { obj["failReason"] = RPCObject(failReason) return obj } + /// initialize the ZksyncTxInfo + /// + /// - Parameter block : the blockNumber containing the tx or `null` if still pending + /// - Parameter executed : true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. + /// - Parameter success : if executed, this property marks the success of the tx. + /// - Parameter failReason : if executed and failed this will include an error message + public init(block: UInt64, executed: Bool, success: Bool, failReason: String) { + self.block = block + self.executed = executed + self.success = success + self.failReason = failReason + } } /// the fees split up into single values @@ -732,6 +804,22 @@ public struct ZksyncTxFee { obj["zkpFee"] = RPCObject(zkpFee) return obj } + /// initialize the ZksyncTxFee + /// + /// - Parameter feeType : Type of the transaaction + /// - Parameter gasFee : the gas for the core-transaction + /// - Parameter gasPriceWei : current gasPrice + /// - Parameter gasTxAmount : gasTxAmount + /// - Parameter totalFee : total of all fees needed to pay in order to execute the transaction + /// - Parameter zkpFee : zkpFee + public init(feeType: String, gasFee: UInt64, gasPriceWei: UInt64, gasTxAmount: UInt64, totalFee: UInt64, zkpFee: UInt64) { + self.feeType = feeType + self.gasFee = gasFee + self.gasPriceWei = gasPriceWei + self.gasTxAmount = gasTxAmount + self.totalFee = totalFee + self.zkpFee = zkpFee + } } /// the transactionReceipt @@ -793,6 +881,30 @@ public struct ZksyncTransactionReceipt { obj["transactionIndex"] = RPCObject(transactionIndex) return obj } + /// initialize the ZksyncTransactionReceipt + /// + /// - Parameter blockNumber : the blockNumber + /// - Parameter blockHash : blockhash if ther containing block + /// - Parameter contractAddress : the deployed contract in case the tx did deploy a new contract + /// - Parameter cumulativeGasUsed : gas used for all transaction up to this one in the block + /// - Parameter gasUsed : gas used by this transaction. + /// - Parameter logs : array of events created during execution of the tx + /// - Parameter logsBloom : bloomfilter used to detect events for `eth_getLogs` + /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure + /// - Parameter transactionHash : requested transactionHash + /// - Parameter transactionIndex : transactionIndex within the containing block. + public init(blockNumber: UInt64, blockHash: String, contractAddress: String, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: ZksyncLogs, logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { + self.blockNumber = blockNumber + self.blockHash = blockHash + self.contractAddress = contractAddress + self.cumulativeGasUsed = cumulativeGasUsed + self.gasUsed = gasUsed + self.logs = logs + self.logsBloom = logsBloom + self.status = status + self.transactionHash = transactionHash + self.transactionIndex = transactionIndex + } } /// array of events created during execution of the tx @@ -859,4 +971,30 @@ public struct ZksyncLogs { obj["type"] = RPCObject(type) return obj } + /// initialize the ZksyncLogs + /// + /// - Parameter address : the address triggering the event. + /// - Parameter blockNumber : the blockNumber + /// - Parameter blockHash : blockhash if ther containing block + /// - Parameter data : abi-encoded data of the event (all non indexed fields) + /// - Parameter logIndex : the index of the even within the block. + /// - Parameter removed : the reorg-status of the event. + /// - Parameter topics : array of 32byte-topics of the indexed fields. + /// - Parameter transactionHash : requested transactionHash + /// - Parameter transactionIndex : transactionIndex within the containing block. + /// - Parameter transactionLogIndex : index of the event within the transaction. + /// - Parameter type : mining-status + public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int, type: String) { + self.address = address + self.blockNumber = blockNumber + self.blockHash = blockHash + self.data = data + self.logIndex = logIndex + self.removed = removed + self.topics = topics + self.transactionHash = transactionHash + self.transactionIndex = transactionIndex + self.transactionLogIndex = transactionLogIndex + self.type = type + } } \ No newline at end of file diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index caf2d5091..cfe1105c8 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -382,6 +382,25 @@ public enum RPCObject: Equatable { self = .dictionary(value.mapValues { RPCObject($0) }) } } + + public func asObject() -> T { + switch self { + case .none: + return 0 as! T + case .integer( let val): + return val as! T + case .string( let val): + return val as! T + case .double(let val): + return val as! T + case .bool( let val): + return val as! T + case .list( let val): + return val.map({(src:RPCObject) -> T in src.asObject() }) as! T + case .dictionary(let val): + return val.mapValues({(src:RPCObject) -> T in src.asObject() }) as! T + } + } } /// Error of a RPC-Request From 950c499726520ab41856c0f6a41cb862e5c9c901 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 10 Apr 2021 20:47:11 +0200 Subject: [PATCH 114/221] fixe eth_getLogs --- c/src/verifier/eth1/basic/rpc.yml | 39 +++++++++++++++++++++++++++++++ c/src/verifier/eth1/nano/rlp.h | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 5b57350ce..9db37e6e4 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -1,5 +1,37 @@ types: + transaction: + to: + descr: receipient of the transaction. + type: address + optional: true + from: + descr: sender of the address (if not sepcified, the first signer will be the sender) + type: address + optional: true + value: + descr: value in wei to send + type: uint256 + optional: true + gas: + descr: the gas to be send along + type: uint64 + optional: true + default: 21000 + gasPrice: + descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` + type: uint64 + optional: true + nonce: + descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` + type: uint64 + optional: true + data: + descr: the data-section of the transaction + type: bytes + optional: true + + blockheader: number: descr: the block number. `null` when its pending block. @@ -702,12 +734,18 @@ eth: topics: descr: Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. type: bytes32 + nullable: true array: true optional: true blockhash: descr: With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. type: bytes32 optional: true + result: + array: true + type: ethlog + descr: array with all found event matching the specified filter + eth_getBalance: @@ -723,6 +761,7 @@ eth: type: uint64 result: descr: the balance + type: uint256 proof: alias: eth_getStorageAt example: diff --git a/c/src/verifier/eth1/nano/rlp.h b/c/src/verifier/eth1/nano/rlp.h index 02822d42f..a277b663b 100644 --- a/c/src/verifier/eth1/nano/rlp.h +++ b/c/src/verifier/eth1/nano/rlp.h @@ -135,7 +135,7 @@ bytes_builder_t* rlp_encode_to_list(bytes_builder_t* bb); /** * converts the data in the builder to a rlp-encoded item. * - * This function is optimized to not increase the memory more than needed and is fastet than + * This function is optimized to not increase the memory more than needed and is faster than * creating a second builder to encode the data. * * \param bb the builder containing the data. From 5990c86c9ad9942fae031572c549f302bae67c81 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 10 Apr 2021 20:47:46 +0200 Subject: [PATCH 115/221] added in3_calcDeployAddress adn support for decoding events --- c/src/api/eth1/rpc.yml | 58 +++++++++++++++++----------------------- c/src/api/eth1/rpc_api.c | 42 ++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index ee3fd8ca1..fda733b68 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -1,35 +1,3 @@ -types: - transaction: - to: - descr: receipient of the transaction. - type: address - from: - descr: sender of the address (if not sepcified, the first signer will be the sender) - type: address - value: - descr: value in wei to send - type: uint256 - optional: true - gas: - descr: the gas to be send along - type: uint64 - optional: true - default: 21000 - gasPrice: - descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint64 - optional: true - nonce: - descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint64 - optional: true - data: - descr: the data-section of the transaction - type: bytes - optional: true - - - utils: descr: | @@ -64,8 +32,12 @@ utils: type: string descr: the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. data: - type: hex + type: bytes descr: the data to decode (usually the result of a eth_call) + topics: + optional: true + type: bytes + descr: in case of an even the topics (concatinated to max 4x32bytes). This is used if indexed.arguments are used. result: type: any array: true @@ -198,6 +170,26 @@ utils: - "0x1234567890" response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + in3_calcDeployAddress: + descr: calculates the address of a contract about to deploy. The address depends on the senders nonce. + params: + sender: + descr: the sender of the transaction + type: address + nonce: + descr: the nonce of the sender during deployment + type: uint64 + optional: true + result: + type: address + descr: the address of the deployed contract + example: + request: + - '0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c' + - 6054986 + response: '0xba866e7bd2573be3eaf5077b557751bb6d58076e' + + net_version: sync: true descr: the Network Version (currently 1) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 052cb7580..b55924676 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -82,14 +82,15 @@ static in3_ret_t in3_abiDecode(in3_rpc_handle_ctx_t* ctx) { CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_STRING) CHECK_PARAM_TYPE(ctx->req, ctx->params, 1, T_BYTES) CHECK_PARAM(ctx->req, ctx->params, 1, val->len % 32 == 0) - char* error = NULL; - json_ctx_t* res = NULL; - char* sig = d_get_string_at(ctx->params, 0); - bytes_t data = d_to_bytes(d_get_at(ctx->params, 1)); - if (d_len(ctx->params) > 2) return req_set_error(ctx->req, "too many arguments (only 2 alllowed)", IN3_EINVAL); + char* error = NULL; + json_ctx_t* res = NULL; + char* sig = d_get_string_at(ctx->params, 0); + bytes_t data = d_to_bytes(d_get_at(ctx->params, 1)); + bytes_t topics = d_to_bytes(d_get_at(ctx->params, 2)); + if (d_len(ctx->params) > 3) return req_set_error(ctx->req, "too many arguments (only 3 alllowed)", IN3_EINVAL); abi_sig_t* req = abi_sig_create(sig, &error); - if (!error) res = abi_decode(req, data, &error); + if (!error) res = topics.data ? abi_decode_event(req, topics, data, &error) : abi_decode(req, data, &error); if (req) abi_sig_free(req); if (error) return req_set_error(ctx->req, error, IN3_EINVAL); char* result = d_create_json(res, res->result); @@ -391,6 +392,34 @@ static in3_ret_t in3_pk2address(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_with_bytes(ctx, bytes(public_key + 1, 64)); } +static in3_ret_t in3_calcDeployAddress(in3_rpc_handle_ctx_t* ctx) { + bytes_t sender = d_to_bytes(d_get_at(ctx->params, 0)); + bytes_t nonce = d_to_bytes(d_get_at(ctx->params, 1)); + if (sender.len != 20) return req_set_error(ctx->req, "Invalid sender address, must be 20 bytes", IN3_EINVAL); + if (!nonce.data) { + sb_t sb = sb_stack(alloca(100)); + sb_add_rawbytes(&sb, "\"0x", sender, 0); + sb_add_chars(&sb, "\",\"latest\""); + d_token_t* result; + TRY(req_send_sub_request(ctx->req, "eth_getTransactionCount", sb.data, NULL, &result, NULL)) + nonce = d_to_bytes(result); + } + + // handle nonce as number, which means no leading zeros and if 0 it should be an empty bytes-array + b_optimize_len(&nonce); + if (nonce.len == 1 && nonce.data[0] == 0) nonce.len = 0; + + bytes_builder_t* bb = bb_new(); + rlp_encode_item(bb, &sender); + rlp_encode_item(bb, &nonce); + rlp_encode_to_list(bb); + bytes32_t hash; + keccak(bb->b, hash); + bb_free(bb); + + return in3_rpc_handle_with_bytes(ctx, bytes(hash + 12, 20)); +} + static in3_ret_t in3_ecrecover(in3_rpc_handle_ctx_t* ctx) { bytes_t msg = d_to_bytes(d_get_at(ctx->params, 0)); bytes_t* sig = d_get_bytes_at(ctx->params, 1); @@ -657,6 +686,7 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("in3_prepareTx", in3_prepareTx(ctx)) TRY_RPC("in3_signTx", in3_signTx(ctx)) TRY_RPC("in3_createKey", in3_createKey(ctx)) + TRY_RPC("in3_calcDeployAddress", in3_calcDeployAddress(ctx)) return IN3_EIGNORE; } From 7418a61b928d94e1dbde770d147866610e96b909 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 10 Apr 2021 20:48:03 +0200 Subject: [PATCH 116/221] fied generator --- c/src/verifier/eth1/full/rpc.yml | 31 +- c/src/verifier/eth1/nano/rpc.yml | 77 +++-- scripts/_in3.sh | 3 +- scripts/generator/swift.js | 31 +- swift/Sources/In3/API/Account.swift | 67 ++-- swift/Sources/In3/API/Btc.swift | 182 +++++----- swift/Sources/In3/API/Contract.swift | 218 +++++++++++- swift/Sources/In3/API/Eth.swift | 466 ++++++++++++-------------- swift/Sources/In3/API/Ipfs.swift | 4 +- swift/Sources/In3/API/Nodelist.swift | 63 ++-- swift/Sources/In3/API/Utils.swift | 47 ++- swift/Sources/In3/API/Zksync.swift | 153 +++++---- swift/Sources/In3/Utils/JsonRpc.swift | 6 + 13 files changed, 770 insertions(+), 578 deletions(-) diff --git a/c/src/verifier/eth1/full/rpc.yml b/c/src/verifier/eth1/full/rpc.yml index 74ab557c5..b83d1d2f8 100644 --- a/c/src/verifier/eth1/full/rpc.yml +++ b/c/src/verifier/eth1/full/rpc.yml @@ -14,6 +14,7 @@ eth: result: descr: the amount of gass needed. + type: uint64 proof: alias: eth_call @@ -23,35 +24,7 @@ eth: params: tx: descr: the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - type: - to: - descr: address of the contract - type: address - from: - descr: sender of the address - type: address - optional: true - value: - descr: value in wei to send - type: uint256 - optional: true - gas: - descr: the gas to be send along - type: uint64 - optional: true - default: 21000 - gasPrice: - descr: the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - type: uint64 - optional: true - nonce: - descr: the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - type: uint64 - optional: true - data: - descr: the data-section of the transaction, which includes the functionhash and the abi-encoded arguments - type: bytes - optional: true + type: transaction block: internalDefault : latest optionalAPI: true diff --git a/c/src/verifier/eth1/nano/rpc.yml b/c/src/verifier/eth1/nano/rpc.yml index e313f4e84..37a7ee990 100644 --- a/c/src/verifier/eth1/nano/rpc.yml +++ b/c/src/verifier/eth1/nano/rpc.yml @@ -1,4 +1,43 @@ types: + + ethlog: + address: + descr: the address triggering the event. + type: address + blockNumber: + descr: the blockNumber + type: uint64 + blockHash: + descr: blockhash if ther containing block + type: bytes32 + data: + descr: abi-encoded data of the event (all non indexed fields) + type: bytes + logIndex: + descr: the index of the even within the block. + type: int + removed: + descr: the reorg-status of the event. + type: bool + topics: + array: true + descr: array of 32byte-topics of the indexed fields. + type: bytes32 + transactionHash: + descr: requested transactionHash + type: bytes32 + transactionIndex: + descr: transactionIndex within the containing block. + type: int + transactionLogIndex: + descr: index of the event within the transaction. + type: int + optional: true + type: + descr: mining-status + type: string + optional: true + transactionReceipt: blockNumber: descr: the blockNumber @@ -9,6 +48,7 @@ types: contractAddress: descr: the deployed contract in case the tx did deploy a new contract type: address + optional: true cumulativeGasUsed: descr: gas used for all transaction up to this one in the block type: uint64 @@ -17,41 +57,8 @@ types: type: uint64 logs: descr: array of events created during execution of the tx - type: - address: - descr: the address triggering the event. - type: address - blockNumber: - descr: the blockNumber - type: uint64 - blockHash: - descr: blockhash if ther containing block - type: bytes32 - data: - descr: abi-encoded data of the event (all non indexed fields) - type: bytes - logIndex: - descr: the index of the even within the block. - type: int - removed: - descr: the reorg-status of the event. - type: bool - topics: - array: true - descr: array of 32byte-topics of the indexed fields. - type: bytes32 - transactionHash: - descr: requested transactionHash - type: bytes32 - transactionIndex: - descr: transactionIndex within the containing block. - type: int - transactionLogIndex: - descr: index of the event within the transaction. - type: int - type: - descr: mining-status - type: string + array: true + type: ethlog logsBloom: descr: bloomfilter used to detect events for `eth_getLogs` type: bytes128 diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 58ee826db..2e9bff2b1 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -59,9 +59,10 @@ subcmds=( 'in3_nodeList: fetches and verifies the nodeList from a node ' 'in3_sign: requests a signed blockhash from the node ' 'in3_whitelist: Returns whitelisted in3-nodes addresses
' - 'in3_abiDecode: based on the ' + 'in3_abiDecode: based on the ' 'in3_abiEncode: based on the ' 'in3_cacheClear: clears the incubed cache (usually found in the ' + 'in3_calcDeployAddress: calculates the address of a contract about to deploy ' 'in3_checksumAddress: Will convert an upper or lowercase Ethereum address to a checksum address
' 'in3_fromWei: converts a given uint (also as hex) with a wei-value into a specified unit ' 'in3_toWei: converts the given value into wei ' diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 4f9a9f2d2..1486ceb6b 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -40,6 +40,13 @@ function converterName(swiftType, asFn) { return asFn ? '{ try ' + type + '($0,$1) }' : type } +function asHex(t, varName) { + if (t.startsWith('UInt256')) + return varName + '.hexValue' + return (t.startsWith('UInt') || t.startsWith('Int')) + ? 'String(format: "0x%1x", arguments: [' + varName + '])' + : varName +} function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api) { typesGenerated[swiftType] = 'placeholder' @@ -52,7 +59,7 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api + '\n guard let obj = try toObject(rpc, optional) else { return nil }' let pubInitHead = ' public init(' let pubInitBody = '' - let pubInitDescr = '\n /// initialize the ' + swiftType + '\n ///' + let pubInitDescr = '\n\n /// initialize the ' + swiftType + '\n ///' for (let name of Object.keys(conf)) { @@ -66,13 +73,18 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api if (p.array) { if (p.optional) { init += '\n if let ' + name + ' = try toArray(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ') {' - init += '\n self.' + name + ' = try ' + name + '.map({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' + init += '\n self.' + name + ' = try ' + name + '.map({ try ' + converterName(t, false) + '($0,' + (p.nullable ? 'true' : 'false') + ')' + (p.nullable ? '' : '!') + ' })' init += '\n } else {' init += '\n self.' + name + ' = nil' init += '\n }' + if (!isStruct(p, typeConfigs)) + toRPC += '\n if let x = ' + name + ' { obj["' + name + '"] = RPCObject( x ) }' } - else + else { init += '\n ' + name + ' = try toArray(obj["' + name + '"])!.map({ try ' + converterName(t, false) + '($0,' + (p.optional ? 'true' : 'false') + ')! })' + if (!isStruct(p, typeConfigs)) + toRPC += '\n obj["' + name + '"] = RPCObject( ' + name + ' )' + } } else if (p.key) { if (p.optional) { @@ -87,8 +99,13 @@ function generateStruct(swiftType, conf, descr, typeConfigs, typesGenerated, api } else { init += '\n ' + name + ' = try ' + converterName(t, false) + '(obj["' + name + '"],' + (p.optional ? 'true' : 'false') + ')!' - if (!isStruct(p, typeConfigs)) - toRPC += '\n obj["' + name + '"] = ' + (p.optional ? (name + ' == nil ? RPCObject.none : RPCObject(' + name + '!)') : 'RPCObject(' + name + ')') + if (!isStruct(p, typeConfigs)) { + if (p.optional || p.optionalAPI) + toRPC += '\n if let x = ' + name + ' { obj["' + name + '"] = RPCObject( ' + asHex(t, 'x') + ' ) }' + else + toRPC += '\n obj["' + name + '"] = RPCObject( ' + asHex(t, name) + ' )' + + } } } @@ -122,7 +139,7 @@ function getAPIType(c, typeConfigs, typesGenerated, prefix, api) { if (typedef && typesGenerated && !typesGenerated[swiftType]) generateStruct(swiftType, typedef, c.descr, typeConfigs, typesGenerated, api); - if (c.array) swiftType = '[' + swiftType + ']' + if (c.array) swiftType = '[' + swiftType + (c.nullable ? '?' : '') + ']' if (c.key) swiftType = '[String:' + swiftType + ']' if (c.optional || c.optionalAPI) swiftType += '?' return swiftType @@ -293,7 +310,7 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc } const paramNames = Object.keys(rpc.params || {}) let x = '\n**Example**\n\n```swift\n' - let call = camelCaseUp(api_name) + 'API(in3).' + fnName + '(' + (ex.request || []) + let call = camelCaseUp(api_name) + '(in3).' + fnName + '(' + (ex.request || []) .filter((_, i) => _ != rpc.params[paramNames[i]].internalDefault) .map((_, i) => paramNames[i] + ': ' + toSwiftValue(_, i)).join(', ') + ')' if (rpc.sync) { diff --git a/swift/Sources/In3/API/Account.swift b/swift/Sources/In3/API/Account.swift index 02ab53870..333e59ba3 100644 --- a/swift/Sources/In3/API/Account.swift +++ b/swift/Sources/In3/API/Account.swift @@ -22,7 +22,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// let result = try Account(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") /// // result = "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" /// ``` /// @@ -37,7 +37,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") + /// let result = try Account(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") /// // result = "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f7818\ /// // 6577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" /// ``` @@ -55,7 +55,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") + /// let result = try Account(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") /// // result = /// // publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c\ /// // 4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" @@ -73,7 +73,7 @@ public class Account { /// **Example** /// /// ```swift - /// AccountAPI(in3).prepareTx(tx: AccountTransaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { + /// Account(in3).prepareTx(tx: AccountTransaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -98,7 +98,7 @@ public class Account { /// **Example** /// /// ```swift - /// AccountAPI(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { + /// Account(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -125,7 +125,7 @@ public class Account { /// **Example** /// /// ```swift - /// AccountAPI(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { + /// Account(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -156,7 +156,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") + /// let result = try Account(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") /// // result = "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" /// ``` /// @@ -174,7 +174,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).createKey() + /// let result = try Account(in3).createKey() /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" /// ``` /// @@ -199,7 +199,7 @@ public class Account { /// **Example** /// /// ```swift - /// AccountAPI(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { + /// Account(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -223,7 +223,7 @@ public class Account { /// **Example** /// /// ```swift - /// AccountAPI(in3).signTransaction(tx: AccountTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { + /// Account(in3).signTransaction(tx: AccountTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -247,7 +247,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") + /// let result = try Account(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") /// // result = "0x2e988a386a799f506693793c6a5af6b54dfaabfb" /// ``` /// @@ -264,7 +264,7 @@ public class Account { /// **Example** /// /// ```swift - /// let result = try AccountAPI(in3).accounts() + /// let result = try Account(in3).accounts() /// // result = /// // - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" /// // - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" @@ -292,10 +292,11 @@ public struct AccountEcrecover { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["publicKey"] = RPCObject(publicKey) - obj["address"] = RPCObject(address) + obj["publicKey"] = RPCObject( publicKey ) + obj["address"] = RPCObject( address ) return obj } + /// initialize the AccountEcrecover /// /// - Parameter publicKey : the public Key of the signer (64 bytes) @@ -309,10 +310,10 @@ public struct AccountEcrecover { /// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). public struct AccountTransaction { /// receipient of the transaction. - public var to: String + public var to: String? /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String + public var from: String? /// value in wei to send public var value: UInt256? @@ -331,8 +332,8 @@ public struct AccountTransaction { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],false)! + to = try toString(obj["to"],true)! + from = try toString(obj["from"],true)! value = try toUInt256(obj["value"],true)! gas = try toUInt64(obj["gas"],true)! gasPrice = try toUInt64(obj["gasPrice"],true)! @@ -342,15 +343,16 @@ public struct AccountTransaction { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = RPCObject(from) - obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) - obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) - obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) - obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) - obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + if let x = to { obj["to"] = RPCObject( x ) } + if let x = from { obj["from"] = RPCObject( x ) } + if let x = value { obj["value"] = RPCObject( x.hexValue ) } + if let x = gas { obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = gasPrice { obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = nonce { obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = data { obj["data"] = RPCObject( x ) } return obj } + /// initialize the AccountTransaction /// /// - Parameter to : receipient of the transaction. @@ -360,7 +362,7 @@ public struct AccountTransaction { /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` /// - Parameter data : the data-section of the transaction - public init(to: String, from: String, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { + public init(to: String? = nil, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { self.to = to self.from = from self.value = value @@ -403,14 +405,15 @@ public struct AccountSignData { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["message"] = RPCObject(message) - obj["messageHash"] = RPCObject(messageHash) - obj["signature"] = RPCObject(signature) - obj["r"] = RPCObject(r) - obj["s"] = RPCObject(s) - obj["v"] = RPCObject(v) + obj["message"] = RPCObject( message ) + obj["messageHash"] = RPCObject( messageHash ) + obj["signature"] = RPCObject( signature ) + obj["r"] = RPCObject( r ) + obj["s"] = RPCObject( s ) + obj["v"] = RPCObject( v ) return obj } + /// initialize the AccountSignData /// /// - Parameter message : original message used diff --git a/swift/Sources/In3/API/Btc.swift b/swift/Sources/In3/API/Btc.swift index a72195544..ce4d1793f 100644 --- a/swift/Sources/In3/API/Btc.swift +++ b/swift/Sources/In3/API/Btc.swift @@ -35,7 +35,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getblockheaderAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// Btc(in3).getblockheaderAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -61,7 +61,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getblockheader(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// Btc(in3).getblockheader(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -102,7 +102,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getBlockAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// Btc(in3).getBlockAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -128,7 +128,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getBlock(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// Btc(in3).getBlock(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -173,7 +173,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getBlockWithTx(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { + /// Btc(in3).getBlockWithTx(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -218,7 +218,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getRawTransactionAsHex(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { + /// Btc(in3).getRawTransactionAsHex(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -244,7 +244,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getRawTransaction(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { + /// Btc(in3).getRawTransaction(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -318,7 +318,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getblockcount() .observe(using: { + /// Btc(in3).getblockcount() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -343,7 +343,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getdifficulty(blocknumber: 631910) .observe(using: { + /// Btc(in3).getdifficulty(blocknumber: 631910) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -370,7 +370,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).proofTarget(target_dap: 230, verified_dap: 200, max_diff: 5, max_dap: 5, limit: 15) .observe(using: { + /// Btc(in3).proofTarget(target_dap: 230, verified_dap: 200, max_diff: 5, max_dap: 5, limit: 15) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -417,7 +417,7 @@ public class Btc { /// **Example** /// /// ```swift - /// BtcAPI(in3).getbestblockhash() .observe(using: { + /// Btc(in3).getbestblockhash() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -506,23 +506,24 @@ public struct Btcblockheader { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject(hash) - obj["confirmations"] = RPCObject(confirmations) - obj["height"] = RPCObject(height) - obj["version"] = RPCObject(version) - obj["versionHex"] = RPCObject(versionHex) - obj["merkleroot"] = RPCObject(merkleroot) - obj["time"] = RPCObject(time) - obj["mediantime"] = RPCObject(mediantime) - obj["nonce"] = RPCObject(nonce) - obj["bits"] = RPCObject(bits) - obj["difficulty"] = RPCObject(difficulty) - obj["chainwork"] = RPCObject(chainwork) - obj["nTx"] = RPCObject(nTx) - obj["previousblockhash"] = RPCObject(previousblockhash) - obj["nextblockhash"] = RPCObject(nextblockhash) + obj["hash"] = RPCObject( hash ) + obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) + obj["height"] = RPCObject( String(format: "0x%1x", arguments: [height]) ) + obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) + obj["versionHex"] = RPCObject( versionHex ) + obj["merkleroot"] = RPCObject( merkleroot ) + obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) + obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["bits"] = RPCObject( bits ) + obj["difficulty"] = RPCObject( difficulty.hexValue ) + obj["chainwork"] = RPCObject( chainwork ) + obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) + obj["previousblockhash"] = RPCObject( previousblockhash ) + obj["nextblockhash"] = RPCObject( nextblockhash ) return obj } + /// initialize the Btcblockheader /// /// - Parameter hash : the block hash (same as provided) @@ -634,23 +635,25 @@ public struct Btcblock { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject(hash) - obj["confirmations"] = RPCObject(confirmations) - obj["height"] = RPCObject(height) - obj["version"] = RPCObject(version) - obj["versionHex"] = RPCObject(versionHex) - obj["merkleroot"] = RPCObject(merkleroot) - obj["time"] = RPCObject(time) - obj["mediantime"] = RPCObject(mediantime) - obj["nonce"] = RPCObject(nonce) - obj["bits"] = RPCObject(bits) - obj["difficulty"] = RPCObject(difficulty) - obj["chainwork"] = RPCObject(chainwork) - obj["nTx"] = RPCObject(nTx) - obj["previousblockhash"] = RPCObject(previousblockhash) - obj["nextblockhash"] = RPCObject(nextblockhash) + obj["hash"] = RPCObject( hash ) + obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) + obj["height"] = RPCObject( height.hexValue ) + obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) + obj["versionHex"] = RPCObject( versionHex ) + obj["merkleroot"] = RPCObject( merkleroot ) + obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) + obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["bits"] = RPCObject( bits ) + obj["difficulty"] = RPCObject( difficulty.hexValue ) + obj["chainwork"] = RPCObject( chainwork ) + obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) + obj["tx"] = RPCObject( tx ) + obj["previousblockhash"] = RPCObject( previousblockhash ) + obj["nextblockhash"] = RPCObject( nextblockhash ) return obj } + /// initialize the Btcblock /// /// - Parameter hash : the block hash (same as provided) @@ -764,23 +767,24 @@ public struct BtcblockWithTx { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject(hash) - obj["confirmations"] = RPCObject(confirmations) - obj["height"] = RPCObject(height) - obj["version"] = RPCObject(version) - obj["versionHex"] = RPCObject(versionHex) - obj["merkleroot"] = RPCObject(merkleroot) - obj["time"] = RPCObject(time) - obj["mediantime"] = RPCObject(mediantime) - obj["nonce"] = RPCObject(nonce) - obj["bits"] = RPCObject(bits) - obj["difficulty"] = RPCObject(difficulty) - obj["chainwork"] = RPCObject(chainwork) - obj["nTx"] = RPCObject(nTx) - obj["previousblockhash"] = RPCObject(previousblockhash) - obj["nextblockhash"] = RPCObject(nextblockhash) + obj["hash"] = RPCObject( hash ) + obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) + obj["height"] = RPCObject( String(format: "0x%1x", arguments: [height]) ) + obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) + obj["versionHex"] = RPCObject( versionHex ) + obj["merkleroot"] = RPCObject( merkleroot ) + obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) + obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["bits"] = RPCObject( bits ) + obj["difficulty"] = RPCObject( difficulty.hexValue ) + obj["chainwork"] = RPCObject( chainwork ) + obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) + obj["previousblockhash"] = RPCObject( previousblockhash ) + obj["nextblockhash"] = RPCObject( nextblockhash ) return obj } + /// initialize the BtcblockWithTx /// /// - Parameter hash : the block hash (same as provided) @@ -887,21 +891,22 @@ public struct Btctransaction { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["txid"] = RPCObject(txid) - obj["in_active_chain"] = RPCObject(in_active_chain) - obj["hex"] = RPCObject(hex) - obj["hash"] = RPCObject(hash) - obj["size"] = RPCObject(size) - obj["vsize"] = RPCObject(vsize) - obj["weight"] = RPCObject(weight) - obj["version"] = RPCObject(version) - obj["locktime"] = RPCObject(locktime) - obj["blockhash"] = RPCObject(blockhash) - obj["confirmations"] = RPCObject(confirmations) - obj["blocktime"] = RPCObject(blocktime) - obj["time"] = RPCObject(time) + obj["txid"] = RPCObject( txid ) + obj["in_active_chain"] = RPCObject( in_active_chain ) + obj["hex"] = RPCObject( hex ) + obj["hash"] = RPCObject( hash ) + obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) + obj["vsize"] = RPCObject( String(format: "0x%1x", arguments: [vsize]) ) + obj["weight"] = RPCObject( String(format: "0x%1x", arguments: [weight]) ) + obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) + obj["locktime"] = RPCObject( String(format: "0x%1x", arguments: [locktime]) ) + obj["blockhash"] = RPCObject( blockhash ) + obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) + obj["blocktime"] = RPCObject( String(format: "0x%1x", arguments: [blocktime]) ) + obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) return obj } + /// initialize the Btctransaction /// /// - Parameter txid : txid @@ -966,11 +971,13 @@ public struct BtcVin { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["txid"] = RPCObject(txid) - obj["vout"] = RPCObject(vout) - obj["sequence"] = RPCObject(sequence) + obj["txid"] = RPCObject( txid ) + obj["vout"] = RPCObject( String(format: "0x%1x", arguments: [vout]) ) + obj["sequence"] = RPCObject( String(format: "0x%1x", arguments: [sequence]) ) + obj["txinwitness"] = RPCObject( txinwitness ) return obj } + /// initialize the BtcVin /// /// - Parameter txid : the transaction id @@ -1003,10 +1010,11 @@ public struct BtcScriptSig { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["asm"] = RPCObject(asm) - obj["hex"] = RPCObject(hex) + obj["asm"] = RPCObject( asm ) + obj["hex"] = RPCObject( hex ) return obj } + /// initialize the BtcScriptSig /// /// - Parameter asm : the asm-codes @@ -1037,10 +1045,11 @@ public struct BtcVout { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["value"] = RPCObject(value) - obj["n"] = RPCObject(n) + obj["value"] = RPCObject( value ) + obj["n"] = RPCObject( String(format: "0x%1x", arguments: [n]) ) return obj } + /// initialize the BtcVout /// /// - Parameter value : The Value in BTC @@ -1081,12 +1090,14 @@ public struct BtcScriptPubKey { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["asm"] = RPCObject(asm) - obj["hex"] = RPCObject(hex) - obj["reqSigs"] = RPCObject(reqSigs) - obj["type"] = RPCObject(type) + obj["asm"] = RPCObject( asm ) + obj["hex"] = RPCObject( hex ) + obj["reqSigs"] = RPCObject( String(format: "0x%1x", arguments: [reqSigs]) ) + obj["type"] = RPCObject( type ) + obj["addresses"] = RPCObject( addresses ) return obj } + /// initialize the BtcScriptPubKey /// /// - Parameter asm : asm @@ -1131,13 +1142,14 @@ public struct BtcProofTarget { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["dap"] = RPCObject(dap) - obj["block"] = RPCObject(block) - obj["final"] = RPCObject(final) - obj["cbtx"] = RPCObject(cbtx) - obj["cbtxMerkleProof"] = RPCObject(cbtxMerkleProof) + obj["dap"] = RPCObject( String(format: "0x%1x", arguments: [dap]) ) + obj["block"] = RPCObject( block ) + obj["final"] = RPCObject( final ) + obj["cbtx"] = RPCObject( cbtx ) + obj["cbtxMerkleProof"] = RPCObject( cbtxMerkleProof ) return obj } + /// initialize the BtcProofTarget /// /// - Parameter dap : the difficulty adjustement period diff --git a/swift/Sources/In3/API/Contract.swift b/swift/Sources/In3/API/Contract.swift index 390e9d9e7..031cf0474 100644 --- a/swift/Sources/In3/API/Contract.swift +++ b/swift/Sources/In3/API/Contract.swift @@ -7,35 +7,129 @@ import Foundation +internal func toHex(val:AnyObject, len:Int=0) -> String { + var s="" + switch val { + case let val as UInt64: + s = String(format: "%1x", arguments: [val]) + case let val as Int: + s = String(format: "%1x", arguments: [val]) + case let val as Double: + s = UInt256(String(val))?.toString(radix: 16) ?? "" + case let val as String: + s = val.replacingOccurrences(of: "0x", with: "") + case let val as Bool: + s = val ? "1" : "0" + case nil: + s = "" + default: + s = "" + } + while s.count < len*2 { + s = "0" + s + } + return "0x" + s +} + public class Contract { var in3:In3 var address:String? var abi:[ABI] + var hashes:[String:ABI] - public init(in3:In3, abi:[ABI], at: String?=nil) throws { + public init(in3:In3, abi:[ABI]? = nil, abiJSON:String? = nil, at: String?=nil) throws { self.in3=in3 - self.abi=abi self.address = at + self.hashes = [:] + if let x = abi { + self.abi=x + } else if let json = abiJSON { + self.abi = try JSONDecoder().decode([ABI].self, from: json.data(using: .utf8)!) + } else { + throw IncubedError.config(message: "No ABI given!") + } + let utils = Utils(in3) + for var a in self.abi { + let hash = try utils.keccak(data: a.inputSignature.replacingOccurrences(of: "indexed ", with: "")) + self.hashes[hash] = a + a.hash = hash + } } - - public func deploy(data: String, args: [AnyObject]) { + public func deploy(data: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + do { + return Eth(in3).sendTransaction(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)) + } catch { + let p = Promise() + p.reject(with: error) + return p + } } - - public func call(name: String, args: [AnyObject]) -> Future<[Any]> { - let p = Promise<[Any]>() - guard let adr = address, let def = self[name] else { - p.reject(with: IncubedError.config(message: "The Contract has no address!")) + + public func deployAndWait(data: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + do { + return Eth(in3).sendTransactionAndWait(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)).chained(using: { + self.address = $0.contractAddress + return Promise(value:$0) + }) + } catch { + let p = Promise() + p.reject(with: error) return p } + } + + public func createDeployTx(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { + if let x = args, x.count>0 { + var tx = try createTx(name: "", args: x, account: account, gas: gas, gasPrice: gasPrice) + tx.data = data + String(tx.data!.suffix(from: tx.data!.index(tx.data!.startIndex, offsetBy: 10))) + return tx + } else { + return EthTransaction( from: account, gas: gas, gasPrice: gasPrice,data : data) + } + } + + public func call(name: String, args: [AnyObject], block: UInt64? = nil, account:String?=nil, gas: UInt64?=nil) -> Future<[Any]> { do { - let data = try encodeCall(name: name, args: args) - return Eth(in3).call(tx: EthTx(to: adr, data: data)).chained(using: { - let res = try Utils(self.in3).abiDecode(signature: def.signature, data : $0) + let tx = try createTx(name: name, args: args, account: account, gas: gas) + return Eth(in3).call(tx: tx, block: block).chained(using: { + let res = try Utils(self.in3).abiDecode(signature: self[name]!.signature, data : $0) return Promise(value: res.map({ $0.asObject() }) as [Any]) }) } catch { + let p = Promise<[Any]>() + p.reject(with: error) + return p + } + } + + public func estimateGas(name: String, args: [AnyObject], account:String?=nil) -> Future { + do { + let tx = try createTx(name: name, args: args, account: account) + return Eth(in3).estimateGas(tx: tx) + } catch { + let p = Promise() + p.reject(with: error) + return p + } + } + + public func sendTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + do { + return Eth(in3).sendTransaction(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) + } catch { + let p = Promise() + p.reject(with: error) + return p + } + } + + public func sendTxAndWait(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + do { + return Eth(in3).sendTransactionAndWait(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) + } catch { + let p = Promise() p.reject(with: error) return p } @@ -50,6 +144,69 @@ public class Contract { } } + + public func createTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { + if let adr = address { + let data = try encodeCall(name: name, args: args) + return EthTransaction(to: adr, from: account, gas: gas ?? 100000, gasPrice: gasPrice, data: data) + } else { + throw IncubedError.config(message: "The Contract has no address!") + } + } + + /// reads events for the given contract + /// if the eventName is omitted all events will be returned. ( in this case filter must be nil ! ) + public func getEvents(eventName:String? = nil, filter: [String:AnyObject]? = nil, fromBlock: UInt64? = nil, toBlock: UInt64? = nil, topics: [String?]?) -> Future<[EthEvent]> { + do { + var t = [String?].init(repeating: nil, count: 4) + if let x = topics { + var i = 0 + for n in x { + t[i] = n + i += 1 + } + } + if let name = eventName { + if filter != nil { + throw IncubedError.config(message: "filter is not allowed when fetiching all event!") + } + guard let def = self[name], let inp = def.inputs else { + throw IncubedError.config(message: "The event \(name) does not exist in the abi definition!") + } + t[0] = def.hash + + if let f = filter { + var i = 0 + for d in inp { + if let x = d.indexed, x { + i += 1 + if let val = f[d.name] { + t[i] = toHex(val: val, len:32) + } + } + } + } + } + + let ef = EthFilter(fromBlock: fromBlock, toBlock: toBlock, address: self.address, topics: t) + return Eth(in3).getLogs(filter: ef).chained(using: { + Promise<[EthEvent]>(value: try $0.map({ (log) -> EthEvent in + if let abi = self.hashes[log.topics[0]] { + return try EthEvent(in3: self.in3, abi: abi, log: log) + } else { + throw IncubedError.config(message: "The eventhash \(log.topics[0]) can not be found in the config!") + } + })) + }) + } catch { + let p = Promise<[EthEvent]>() + p.reject(with: error) + return p + } + } + + + subscript(name: String) -> ABI? { get { return self.abi.first(where:{ $0.name == name }) @@ -73,14 +230,17 @@ public struct ABI : Codable { public var type: String public var internalType: String? public var signature:String { + if let r = outputs { + return inputSignature + ":(\( r.map({ $0.signature }).joined(separator: ",") ))" + } else { + return inputSignature + } + } + public var inputSignature:String { guard let inp = inputs, let name = self.name else { return "\(self.name ?? "_")()" } - var sig = "\(name)(\( inp.map({ $0.signature }).joined(separator: ",") ))" - if let r = outputs { - sig += ":(\( r.map({ $0.signature }).joined(separator: ",") ))" - } - return sig + return "\(name == "" ? "_" : name)(\( inp.map({ $0.signature }).joined(separator: ",") ))" } } @@ -100,8 +260,32 @@ public struct ABIField : Codable { if baseType == "tuple", let cs = components { baseType = "(\(cs.map({ $0.signature }).joined(separator: ",")))" } + if let x = indexed, x { + return "indexed " + baseType + } return baseType + array } } +public struct EthEvent { + public var log:Ethlog + public var event:String + public var values:[String:AnyObject] + + init(in3:In3, abi:ABI, log:Ethlog) throws { + self.log = log + self.event = abi.name ?? "" + self.values = [:] + if let inp = abi.inputs { + let vals = try Utils(in3).abiDecode(signature: abi.inputSignature, data: log.data, topics: "0x"+log.topics.map({ $0.replacingOccurrences(of: "0x", with: "")}).joined(separator: "")) + var i = 0 + for a in inp { + let r = vals[i] + self.values[a.name] = r.asObject() + i += 1 + } + } + } + +} diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift index 34a5c18c9..e1b82b5d1 100644 --- a/swift/Sources/In3/API/Eth.swift +++ b/swift/Sources/In3/API/Eth.swift @@ -49,7 +49,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).blockNumber() .observe(using: { + /// Eth(in3).blockNumber() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -72,7 +72,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getBlock() .observe(using: { + /// Eth(in3).getBlock() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -123,7 +123,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getBlockWithTx() .observe(using: { + /// Eth(in3).getBlockWithTx() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -174,7 +174,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getBlockByHash(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { + /// Eth(in3).getBlockByHash(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -225,7 +225,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getBlockByHashWithTx(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { + /// Eth(in3).getBlockByHashWithTx(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -308,7 +308,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionByBlockHashAndIndex(blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee", index: "0xd5") .observe(using: { + /// Eth(in3).getTransactionByBlockHashAndIndex(blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee", index: "0xd5") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -350,7 +350,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionByBlockNumberAndIndex(blockNumber: "0xb8a4a9", index: "0xd5") .observe(using: { + /// Eth(in3).getTransactionByBlockNumberAndIndex(blockNumber: "0xb8a4a9", index: "0xd5") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -391,7 +391,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionByHash(txHash: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b") .observe(using: { + /// Eth(in3).getTransactionByHash(txHash: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -424,8 +424,9 @@ public class Eth { /// searches for events matching the given criteria. See [eth_getLogs](https://eth.wiki/json-rpc/API#eth_getLogs) for the spec. /// - Parameter filter : The filter criteria for the events. - public func getLogs(filter: EthFilter) -> Future { - return execAndConvert(in3: in3, method: "eth_getLogs", params:RPCObject( filter.toRPCDict()), convertWith: toString ) + /// - Returns: array with all found event matching the specified filter + public func getLogs(filter: EthFilter) -> Future<[Ethlog]> { + return execAndConvert(in3: in3, method: "eth_getLogs", params:RPCObject( filter.toRPCDict()), convertWith: { try toArray($0,$1)!.map({ try Ethlog($0,false)! }) } ) } /// gets the balance of an account for a given block @@ -436,7 +437,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { + /// Eth(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -448,8 +449,8 @@ public class Eth { /// /// ``` /// - public func getBalance(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getBalance", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) + public func getBalance(account: String, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_getBalance", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toUInt256 ) } /// gets the nonce or number of transaction sent from this account at a given block @@ -460,7 +461,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { + /// Eth(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -484,7 +485,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f") .observe(using: { + /// Eth(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -509,7 +510,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0") .observe(using: { + /// Eth(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -550,8 +551,8 @@ public class Eth { /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). /// - Parameter block : the blockNumber or `latest` /// - Returns: the amount of gass needed. - public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_estimateGas", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) + public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "eth_estimateGas", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toUInt64 ) } /// calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) @@ -562,7 +563,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).call(tx: EthTx(to: "0x2736D225f85740f42D17987100dc8d58e9e16252", data: "0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001")) .observe(using: { + /// Eth(in3).call(tx: EthTransaction(to: "0x2736D225f85740f42D17987100dc8d58e9e16252", data: "0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001")) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -574,7 +575,7 @@ public class Eth { /// /// ``` /// - public func call(tx: EthTx, block: UInt64? = nil) -> Future { + public func call(tx: EthTransaction, block: UInt64? = nil) -> Future { return execAndConvert(in3: in3, method: "eth_call", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) } @@ -585,7 +586,7 @@ public class Eth { /// **Example** /// /// ```swift - /// EthAPI(in3).getTransactionReceipt(txHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e") .observe(using: { + /// Eth(in3).getTransactionReceipt(txHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -712,25 +713,28 @@ public struct EthBlockdataWithTxHashes { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["number"] = RPCObject(number) - obj["hash"] = RPCObject(hash) - obj["parentHash"] = RPCObject(parentHash) - obj["nonce"] = RPCObject(nonce) - obj["sha3Uncles"] = RPCObject(sha3Uncles) - obj["logsBloom"] = RPCObject(logsBloom) - obj["transactionsRoot"] = RPCObject(transactionsRoot) - obj["stateRoot"] = RPCObject(stateRoot) - obj["receiptsRoot"] = RPCObject(receiptsRoot) - obj["miner"] = RPCObject(miner) - obj["difficulty"] = RPCObject(difficulty) - obj["totalDifficulty"] = RPCObject(totalDifficulty) - obj["extraData"] = RPCObject(extraData) - obj["size"] = RPCObject(size) - obj["gasLimit"] = RPCObject(gasLimit) - obj["gasUsed"] = RPCObject(gasUsed) - obj["timestamp"] = RPCObject(timestamp) + obj["transactions"] = RPCObject( transactions ) + obj["number"] = RPCObject( String(format: "0x%1x", arguments: [number]) ) + obj["hash"] = RPCObject( hash ) + obj["parentHash"] = RPCObject( parentHash ) + obj["nonce"] = RPCObject( nonce.hexValue ) + obj["sha3Uncles"] = RPCObject( sha3Uncles ) + obj["logsBloom"] = RPCObject( logsBloom ) + obj["transactionsRoot"] = RPCObject( transactionsRoot ) + obj["stateRoot"] = RPCObject( stateRoot ) + obj["receiptsRoot"] = RPCObject( receiptsRoot ) + obj["miner"] = RPCObject( miner ) + obj["difficulty"] = RPCObject( difficulty.hexValue ) + obj["totalDifficulty"] = RPCObject( totalDifficulty.hexValue ) + obj["extraData"] = RPCObject( extraData ) + obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) + obj["gasLimit"] = RPCObject( String(format: "0x%1x", arguments: [gasLimit]) ) + obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) + obj["timestamp"] = RPCObject( String(format: "0x%1x", arguments: [timestamp]) ) + obj["uncles"] = RPCObject( uncles ) return obj } + /// initialize the EthBlockdataWithTxHashes /// /// - Parameter transactions : Array of transaction hashes @@ -859,25 +863,27 @@ public struct EthBlockdata { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["number"] = RPCObject(number) - obj["hash"] = RPCObject(hash) - obj["parentHash"] = RPCObject(parentHash) - obj["nonce"] = RPCObject(nonce) - obj["sha3Uncles"] = RPCObject(sha3Uncles) - obj["logsBloom"] = RPCObject(logsBloom) - obj["transactionsRoot"] = RPCObject(transactionsRoot) - obj["stateRoot"] = RPCObject(stateRoot) - obj["receiptsRoot"] = RPCObject(receiptsRoot) - obj["miner"] = RPCObject(miner) - obj["difficulty"] = RPCObject(difficulty) - obj["totalDifficulty"] = RPCObject(totalDifficulty) - obj["extraData"] = RPCObject(extraData) - obj["size"] = RPCObject(size) - obj["gasLimit"] = RPCObject(gasLimit) - obj["gasUsed"] = RPCObject(gasUsed) - obj["timestamp"] = RPCObject(timestamp) + obj["number"] = RPCObject( String(format: "0x%1x", arguments: [number]) ) + obj["hash"] = RPCObject( hash ) + obj["parentHash"] = RPCObject( parentHash ) + obj["nonce"] = RPCObject( nonce.hexValue ) + obj["sha3Uncles"] = RPCObject( sha3Uncles ) + obj["logsBloom"] = RPCObject( logsBloom ) + obj["transactionsRoot"] = RPCObject( transactionsRoot ) + obj["stateRoot"] = RPCObject( stateRoot ) + obj["receiptsRoot"] = RPCObject( receiptsRoot ) + obj["miner"] = RPCObject( miner ) + obj["difficulty"] = RPCObject( difficulty.hexValue ) + obj["totalDifficulty"] = RPCObject( totalDifficulty.hexValue ) + obj["extraData"] = RPCObject( extraData ) + obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) + obj["gasLimit"] = RPCObject( String(format: "0x%1x", arguments: [gasLimit]) ) + obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) + obj["timestamp"] = RPCObject( String(format: "0x%1x", arguments: [timestamp]) ) + obj["uncles"] = RPCObject( uncles ) return obj } + /// initialize the EthBlockdata /// /// - Parameter transactions : Array of transaction objects @@ -986,22 +992,23 @@ public struct EthTransactiondata { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = RPCObject(from) - obj["value"] = RPCObject(value) - obj["gas"] = RPCObject(gas) - obj["gasPrice"] = RPCObject(gasPrice) - obj["nonce"] = RPCObject(nonce) - obj["blockHash"] = RPCObject(blockHash) - obj["blockNumber"] = RPCObject(blockNumber) - obj["hash"] = RPCObject(hash) - obj["input"] = RPCObject(input) - obj["transactionIndex"] = RPCObject(transactionIndex) - obj["v"] = RPCObject(v) - obj["r"] = RPCObject(r) - obj["s"] = RPCObject(s) + obj["to"] = RPCObject( to ) + obj["from"] = RPCObject( from ) + obj["value"] = RPCObject( value.hexValue ) + obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [gas]) ) + obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [gasPrice]) ) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["blockHash"] = RPCObject( blockHash ) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + obj["hash"] = RPCObject( hash ) + obj["input"] = RPCObject( input ) + obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) + obj["v"] = RPCObject( v ) + obj["r"] = RPCObject( r ) + obj["s"] = RPCObject( s ) return obj } + /// initialize the EthTransactiondata /// /// - Parameter to : receipient of the transaction. @@ -1048,7 +1055,7 @@ public struct EthFilter { public var address: String? /// Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. - public var topics: [String]? + public var topics: [String?]? /// With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. public var blockhash: String? @@ -1059,7 +1066,7 @@ public struct EthFilter { toBlock = try toUInt64(obj["toBlock"],true)! address = try toString(obj["address"],true)! if let topics = try toArray(obj["topics"],true) { - self.topics = try topics.map({ try toString($0,true)! }) + self.topics = try topics.map({ try toString($0,true) }) } else { self.topics = nil } @@ -1068,12 +1075,14 @@ public struct EthFilter { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["fromBlock"] = fromBlock == nil ? RPCObject.none : RPCObject(fromBlock!) - obj["toBlock"] = toBlock == nil ? RPCObject.none : RPCObject(toBlock!) - obj["address"] = address == nil ? RPCObject.none : RPCObject(address!) - obj["blockhash"] = blockhash == nil ? RPCObject.none : RPCObject(blockhash!) + if let x = fromBlock { obj["fromBlock"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = toBlock { obj["toBlock"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = address { obj["address"] = RPCObject( x ) } + if let x = topics { obj["topics"] = RPCObject( x ) } + if let x = blockhash { obj["blockhash"] = RPCObject( x ) } return obj } + /// initialize the EthFilter /// /// - Parameter fromBlock : Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. @@ -1081,7 +1090,7 @@ public struct EthFilter { /// - Parameter address : Contract address or a list of addresses from which logs should originate. /// - Parameter topics : Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. /// - Parameter blockhash : With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. - public init(fromBlock: UInt64? = nil, toBlock: UInt64? = nil, address: String? = nil, topics: [String]? = nil, blockhash: String? = nil) { + public init(fromBlock: UInt64? = nil, toBlock: UInt64? = nil, address: String? = nil, topics: [String?]? = nil, blockhash: String? = nil) { self.fromBlock = fromBlock self.toBlock = toBlock self.address = address @@ -1090,13 +1099,107 @@ public struct EthFilter { } } +/// array with all found event matching the specified filter +public struct Ethlog { + /// the address triggering the event. + public var address: String + + /// the blockNumber + public var blockNumber: UInt64 + + /// blockhash if ther containing block + public var blockHash: String + + /// abi-encoded data of the event (all non indexed fields) + public var data: String + + /// the index of the even within the block. + public var logIndex: Int + + /// the reorg-status of the event. + public var removed: Bool + + /// array of 32byte-topics of the indexed fields. + public var topics: [String] + + /// requested transactionHash + public var transactionHash: String + + /// transactionIndex within the containing block. + public var transactionIndex: Int + + /// index of the event within the transaction. + public var transactionLogIndex: Int? + + /// mining-status + public var type: String? + + internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { + guard let obj = try toObject(rpc, optional) else { return nil } + address = try toString(obj["address"],false)! + blockNumber = try toUInt64(obj["blockNumber"],false)! + blockHash = try toString(obj["blockHash"],false)! + data = try toString(obj["data"],false)! + logIndex = try toInt(obj["logIndex"],false)! + removed = try toBool(obj["removed"],false)! + topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) + transactionHash = try toString(obj["transactionHash"],false)! + transactionIndex = try toInt(obj["transactionIndex"],false)! + transactionLogIndex = try toInt(obj["transactionLogIndex"],true)! + type = try toString(obj["type"],true)! + } + + internal func toRPCDict() -> [String:RPCObject] { + var obj:[String:RPCObject] = [:] + obj["address"] = RPCObject( address ) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + obj["blockHash"] = RPCObject( blockHash ) + obj["data"] = RPCObject( data ) + obj["logIndex"] = RPCObject( String(format: "0x%1x", arguments: [logIndex]) ) + obj["removed"] = RPCObject( removed ) + obj["topics"] = RPCObject( topics ) + obj["transactionHash"] = RPCObject( transactionHash ) + obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) + if let x = transactionLogIndex { obj["transactionLogIndex"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = type { obj["type"] = RPCObject( x ) } + return obj + } + + /// initialize the Ethlog + /// + /// - Parameter address : the address triggering the event. + /// - Parameter blockNumber : the blockNumber + /// - Parameter blockHash : blockhash if ther containing block + /// - Parameter data : abi-encoded data of the event (all non indexed fields) + /// - Parameter logIndex : the index of the even within the block. + /// - Parameter removed : the reorg-status of the event. + /// - Parameter topics : array of 32byte-topics of the indexed fields. + /// - Parameter transactionHash : requested transactionHash + /// - Parameter transactionIndex : transactionIndex within the containing block. + /// - Parameter transactionLogIndex : index of the event within the transaction. + /// - Parameter type : mining-status + public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int? = nil, type: String? = nil) { + self.address = address + self.blockNumber = blockNumber + self.blockHash = blockHash + self.data = data + self.logIndex = logIndex + self.removed = removed + self.topics = topics + self.transactionHash = transactionHash + self.transactionIndex = transactionIndex + self.transactionLogIndex = transactionLogIndex + self.type = type + } +} + /// the transactiondata to send public struct EthTransaction { /// receipient of the transaction. - public var to: String + public var to: String? /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String + public var from: String? /// value in wei to send public var value: UInt256? @@ -1115,8 +1218,8 @@ public struct EthTransaction { internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],false)! + to = try toString(obj["to"],true)! + from = try toString(obj["from"],true)! value = try toUInt256(obj["value"],true)! gas = try toUInt64(obj["gas"],true)! gasPrice = try toUInt64(obj["gasPrice"],true)! @@ -1126,15 +1229,16 @@ public struct EthTransaction { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = RPCObject(from) - obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) - obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) - obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) - obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) - obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) + if let x = to { obj["to"] = RPCObject( x ) } + if let x = from { obj["from"] = RPCObject( x ) } + if let x = value { obj["value"] = RPCObject( x.hexValue ) } + if let x = gas { obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = gasPrice { obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = nonce { obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = data { obj["data"] = RPCObject( x ) } return obj } + /// initialize the EthTransaction /// /// - Parameter to : receipient of the transaction. @@ -1144,7 +1248,7 @@ public struct EthTransaction { /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` /// - Parameter data : the data-section of the transaction - public init(to: String, from: String, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { + public init(to: String? = nil, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { self.to = to self.from = from self.value = value @@ -1164,7 +1268,7 @@ public struct EthTransactionReceipt { public var blockHash: String /// the deployed contract in case the tx did deploy a new contract - public var contractAddress: String + public var contractAddress: String? /// gas used for all transaction up to this one in the block public var cumulativeGasUsed: UInt64 @@ -1173,7 +1277,7 @@ public struct EthTransactionReceipt { public var gasUsed: UInt64 /// array of events created during execution of the tx - public var logs: EthLogs + public var logs: [Ethlog] /// bloomfilter used to detect events for `eth_getLogs` public var logsBloom: String @@ -1191,10 +1295,10 @@ public struct EthTransactionReceipt { guard let obj = try toObject(rpc, optional) else { return nil } blockNumber = try toUInt64(obj["blockNumber"],false)! blockHash = try toString(obj["blockHash"],false)! - contractAddress = try toString(obj["contractAddress"],false)! + contractAddress = try toString(obj["contractAddress"],true)! cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! gasUsed = try toUInt64(obj["gasUsed"],false)! - logs = try EthLogs(obj["logs"],false)! + logs = try toArray(obj["logs"])!.map({ try Ethlog($0,false)! }) logsBloom = try toString(obj["logsBloom"],false)! status = try toInt(obj["status"],false)! transactionHash = try toString(obj["transactionHash"],false)! @@ -1203,17 +1307,18 @@ public struct EthTransactionReceipt { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject(blockNumber) - obj["blockHash"] = RPCObject(blockHash) - obj["contractAddress"] = RPCObject(contractAddress) - obj["cumulativeGasUsed"] = RPCObject(cumulativeGasUsed) - obj["gasUsed"] = RPCObject(gasUsed) - obj["logsBloom"] = RPCObject(logsBloom) - obj["status"] = RPCObject(status) - obj["transactionHash"] = RPCObject(transactionHash) - obj["transactionIndex"] = RPCObject(transactionIndex) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + obj["blockHash"] = RPCObject( blockHash ) + if let x = contractAddress { obj["contractAddress"] = RPCObject( x ) } + obj["cumulativeGasUsed"] = RPCObject( String(format: "0x%1x", arguments: [cumulativeGasUsed]) ) + obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) + obj["logsBloom"] = RPCObject( logsBloom ) + obj["status"] = RPCObject( String(format: "0x%1x", arguments: [status]) ) + obj["transactionHash"] = RPCObject( transactionHash ) + obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) return obj } + /// initialize the EthTransactionReceipt /// /// - Parameter blockNumber : the blockNumber @@ -1226,7 +1331,7 @@ public struct EthTransactionReceipt { /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure /// - Parameter transactionHash : requested transactionHash /// - Parameter transactionIndex : transactionIndex within the containing block. - public init(blockNumber: UInt64, blockHash: String, contractAddress: String, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: EthLogs, logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { + public init(blockNumber: UInt64, blockHash: String, contractAddress: String? = nil, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: [Ethlog], logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { self.blockNumber = blockNumber self.blockHash = blockHash self.contractAddress = contractAddress @@ -1238,161 +1343,4 @@ public struct EthTransactionReceipt { self.transactionHash = transactionHash self.transactionIndex = transactionIndex } -} - -/// array of events created during execution of the tx -public struct EthLogs { - /// the address triggering the event. - public var address: String - - /// the blockNumber - public var blockNumber: UInt64 - - /// blockhash if ther containing block - public var blockHash: String - - /// abi-encoded data of the event (all non indexed fields) - public var data: String - - /// the index of the even within the block. - public var logIndex: Int - - /// the reorg-status of the event. - public var removed: Bool - - /// array of 32byte-topics of the indexed fields. - public var topics: [String] - - /// requested transactionHash - public var transactionHash: String - - /// transactionIndex within the containing block. - public var transactionIndex: Int - - /// index of the event within the transaction. - public var transactionLogIndex: Int - - /// mining-status - public var type: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - address = try toString(obj["address"],false)! - blockNumber = try toUInt64(obj["blockNumber"],false)! - blockHash = try toString(obj["blockHash"],false)! - data = try toString(obj["data"],false)! - logIndex = try toInt(obj["logIndex"],false)! - removed = try toBool(obj["removed"],false)! - topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) - transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toInt(obj["transactionIndex"],false)! - transactionLogIndex = try toInt(obj["transactionLogIndex"],false)! - type = try toString(obj["type"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject(address) - obj["blockNumber"] = RPCObject(blockNumber) - obj["blockHash"] = RPCObject(blockHash) - obj["data"] = RPCObject(data) - obj["logIndex"] = RPCObject(logIndex) - obj["removed"] = RPCObject(removed) - obj["transactionHash"] = RPCObject(transactionHash) - obj["transactionIndex"] = RPCObject(transactionIndex) - obj["transactionLogIndex"] = RPCObject(transactionLogIndex) - obj["type"] = RPCObject(type) - return obj - } - /// initialize the EthLogs - /// - /// - Parameter address : the address triggering the event. - /// - Parameter blockNumber : the blockNumber - /// - Parameter blockHash : blockhash if ther containing block - /// - Parameter data : abi-encoded data of the event (all non indexed fields) - /// - Parameter logIndex : the index of the even within the block. - /// - Parameter removed : the reorg-status of the event. - /// - Parameter topics : array of 32byte-topics of the indexed fields. - /// - Parameter transactionHash : requested transactionHash - /// - Parameter transactionIndex : transactionIndex within the containing block. - /// - Parameter transactionLogIndex : index of the event within the transaction. - /// - Parameter type : mining-status - public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int, type: String) { - self.address = address - self.blockNumber = blockNumber - self.blockHash = blockHash - self.data = data - self.logIndex = logIndex - self.removed = removed - self.topics = topics - self.transactionHash = transactionHash - self.transactionIndex = transactionIndex - self.transactionLogIndex = transactionLogIndex - self.type = type - } -} - -/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). -public struct EthTx { - /// address of the contract - public var to: String - - /// sender of the address - public var from: String? - - /// value in wei to send - public var value: UInt256? - - /// the gas to be send along - public var gas: UInt64? - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64? - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64? - - /// the data-section of the transaction, which includes the functionhash and the abi-encoded arguments - public var data: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],true)! - value = try toUInt256(obj["value"],true)! - gas = try toUInt64(obj["gas"],true)! - gasPrice = try toUInt64(obj["gasPrice"],true)! - nonce = try toUInt64(obj["nonce"],true)! - data = try toString(obj["data"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject(to) - obj["from"] = from == nil ? RPCObject.none : RPCObject(from!) - obj["value"] = value == nil ? RPCObject.none : RPCObject(value!) - obj["gas"] = gas == nil ? RPCObject.none : RPCObject(gas!) - obj["gasPrice"] = gasPrice == nil ? RPCObject.none : RPCObject(gasPrice!) - obj["nonce"] = nonce == nil ? RPCObject.none : RPCObject(nonce!) - obj["data"] = data == nil ? RPCObject.none : RPCObject(data!) - return obj - } - /// initialize the EthTx - /// - /// - Parameter to : address of the contract - /// - Parameter from : sender of the address - /// - Parameter value : value in wei to send - /// - Parameter gas : the gas to be send along - /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - /// - Parameter data : the data-section of the transaction, which includes the functionhash and the abi-encoded arguments - public init(to: String, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { - self.to = to - self.from = from - self.value = value - self.gas = gas - self.gasPrice = gasPrice - self.nonce = nonce - self.data = data - } } \ No newline at end of file diff --git a/swift/Sources/In3/API/Ipfs.swift b/swift/Sources/In3/API/Ipfs.swift index c9db9028c..7911e3c72 100644 --- a/swift/Sources/In3/API/Ipfs.swift +++ b/swift/Sources/In3/API/Ipfs.swift @@ -23,7 +23,7 @@ public class Ipfs { /// **Example** /// /// ```swift - /// IpfsAPI(in3).get(ipfshash: "QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD", encoding: "utf8") .observe(using: { + /// Ipfs(in3).get(ipfshash: "QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD", encoding: "utf8") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -50,7 +50,7 @@ public class Ipfs { /// **Example** /// /// ```swift - /// IpfsAPI(in3).put(data: "I love Incubed", encoding: "utf8") .observe(using: { + /// Ipfs(in3).put(data: "I love Incubed", encoding: "utf8") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") diff --git a/swift/Sources/In3/API/Nodelist.swift b/swift/Sources/In3/API/Nodelist.swift index 9b823613c..81796ff22 100644 --- a/swift/Sources/In3/API/Nodelist.swift +++ b/swift/Sources/In3/API/Nodelist.swift @@ -21,7 +21,7 @@ public class Nodelist { /// **Example** /// /// ```swift - /// NodelistAPI(in3).nodes(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { + /// Nodelist(in3).nodes(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -73,7 +73,7 @@ public class Nodelist { /// **Example** /// /// ```swift - /// NodelistAPI(in3).signBlockHash(blocks: NodelistBlocks(blockNumber: 8770580)) .observe(using: { + /// Nodelist(in3).signBlockHash(blocks: NodelistBlocks(blockNumber: 8770580)) .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -102,7 +102,7 @@ public class Nodelist { /// **Example** /// /// ```swift - /// NodelistAPI(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { + /// Nodelist(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -154,12 +154,13 @@ public struct NodeListDefinition { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["contract"] = RPCObject(contract) - obj["registryId"] = RPCObject(registryId) - obj["lastBlockNumber"] = RPCObject(lastBlockNumber) - obj["totalServer"] = RPCObject(totalServer) + obj["contract"] = RPCObject( contract ) + obj["registryId"] = RPCObject( registryId ) + obj["lastBlockNumber"] = RPCObject( String(format: "0x%1x", arguments: [lastBlockNumber]) ) + obj["totalServer"] = RPCObject( String(format: "0x%1x", arguments: [totalServer]) ) return obj } + /// initialize the NodeListDefinition /// /// - Parameter nodes : a array of node definitions. @@ -224,17 +225,18 @@ public struct Node { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["url"] = RPCObject(url) - obj["address"] = RPCObject(address) - obj["index"] = RPCObject(index) - obj["deposit"] = RPCObject(deposit) - obj["props"] = RPCObject(props) - obj["timeout"] = RPCObject(timeout) - obj["registerTime"] = RPCObject(registerTime) - obj["weight"] = RPCObject(weight) - obj["proofHash"] = RPCObject(proofHash) + obj["url"] = RPCObject( url ) + obj["address"] = RPCObject( address ) + obj["index"] = RPCObject( String(format: "0x%1x", arguments: [index]) ) + obj["deposit"] = RPCObject( deposit.hexValue ) + obj["props"] = RPCObject( props ) + obj["timeout"] = RPCObject( String(format: "0x%1x", arguments: [timeout]) ) + obj["registerTime"] = RPCObject( String(format: "0x%1x", arguments: [registerTime]) ) + obj["weight"] = RPCObject( String(format: "0x%1x", arguments: [weight]) ) + obj["proofHash"] = RPCObject( proofHash ) return obj } + /// initialize the Node /// /// - Parameter url : the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. @@ -279,10 +281,11 @@ public struct NodelistBlocks { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject(blockNumber) - obj["hash"] = hash == nil ? RPCObject.none : RPCObject(hash!) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + if let x = hash { obj["hash"] = RPCObject( x ) } return obj } + /// initialize the NodelistBlocks /// /// - Parameter blockNumber : the blockNumber to sign @@ -325,14 +328,15 @@ public struct NodelistSignBlockHash { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["blockHash"] = RPCObject(blockHash) - obj["block"] = RPCObject(block) - obj["r"] = RPCObject(r) - obj["s"] = RPCObject(s) - obj["v"] = RPCObject(v) - obj["msgHash"] = RPCObject(msgHash) + obj["blockHash"] = RPCObject( blockHash ) + obj["block"] = RPCObject( String(format: "0x%1x", arguments: [block]) ) + obj["r"] = RPCObject( r ) + obj["s"] = RPCObject( s ) + obj["v"] = RPCObject( v ) + obj["msgHash"] = RPCObject( msgHash ) return obj } + /// initialize the NodelistSignBlockHash /// /// - Parameter blockHash : the blockhash which was signed. @@ -379,13 +383,14 @@ public struct NodelistWhitelist { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["nodes"] = RPCObject(nodes) - obj["lastWhiteList"] = RPCObject(lastWhiteList) - obj["contract"] = RPCObject(contract) - obj["lastBlockNumber"] = RPCObject(lastBlockNumber) - obj["totalServer"] = RPCObject(totalServer) + obj["nodes"] = RPCObject( nodes ) + obj["lastWhiteList"] = RPCObject( String(format: "0x%1x", arguments: [lastWhiteList]) ) + obj["contract"] = RPCObject( contract ) + obj["lastBlockNumber"] = RPCObject( String(format: "0x%1x", arguments: [lastBlockNumber]) ) + obj["totalServer"] = RPCObject( String(format: "0x%1x", arguments: [totalServer]) ) return obj } + /// initialize the NodelistWhitelist /// /// - Parameter nodes : array of whitelisted nodes addresses. diff --git a/swift/Sources/In3/API/Utils.swift b/swift/Sources/In3/API/Utils.swift index 0e8d4e973..c39f21573 100644 --- a/swift/Sources/In3/API/Utils.swift +++ b/swift/Sources/In3/API/Utils.swift @@ -21,7 +21,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) + /// let result = try Utils(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) /// // result = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" /// ``` /// @@ -32,19 +32,20 @@ public class Utils { /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. /// - Parameter data : the data to decode (usually the result of a eth_call) + /// - Parameter topics : in case of an even the topics (concatinated to max 4x32bytes). This is used if indexed.arguments are used. /// - Returns: a array with the values after decodeing. /// /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") + /// let result = try Utils(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") /// // result = /// // - "0x1234567890123456789012345678901234567890" /// // - "0x05" /// ``` /// - public func abiDecode(signature: String, data: String) throws -> [RPCObject] { - return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), convertWith: { try toArray($0,$1)! } ) + public func abiDecode(signature: String, data: String, topics: String? = nil) throws -> [RPCObject] { + return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), topics == nil ? RPCObject.none : RPCObject( topics! ), convertWith: { try toArray($0,$1)! } ) } /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) @@ -55,7 +56,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) + /// let result = try Utils(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" /// ``` /// @@ -71,7 +72,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).toWei(value: "20.0009123", unit: "eth") + /// let result = try Utils(in3).toWei(value: "20.0009123", unit: "eth") /// // result = "0x01159183c4793db800" /// ``` /// @@ -88,7 +89,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) + /// let result = try Utils(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) /// // result = "0.158" /// ``` /// @@ -102,7 +103,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).cacheClear() + /// let result = try Utils(in3).cacheClear() /// // result = true /// ``` /// @@ -128,7 +129,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).keccak(data: "0x1234567890") + /// let result = try Utils(in3).keccak(data: "0x1234567890") /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" /// ``` /// @@ -148,7 +149,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).sha3(data: "0x1234567890") + /// let result = try Utils(in3).sha3(data: "0x1234567890") /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" /// ``` /// @@ -166,7 +167,7 @@ public class Utils { /// **Example** /// /// ```swift - /// let result = try UtilsAPI(in3).sha256(data: "0x1234567890") + /// let result = try Utils(in3).sha256(data: "0x1234567890") /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" /// ``` /// @@ -174,6 +175,30 @@ public class Utils { return try execLocalAndConvert(in3: in3, method: "sha256", params:RPCObject( data), convertWith: toString ) } + /// calculates the address of a contract about to deploy. The address depends on the senders nonce. + /// - Parameter sender : the sender of the transaction + /// - Parameter nonce : the nonce of the sender during deployment + /// - Returns: the address of the deployed contract + /// + /// **Example** + /// + /// ```swift + /// Utils(in3).calcDeployAddress(sender: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c", nonce: 6054986) .observe(using: { + /// switch $0 { + /// case let .failure(err): + /// print("Failed because : \(err.localizedDescription)") + /// case let .success(val): + /// print("result : \(val)") + /// // result = "0xba866e7bd2573be3eaf5077b557751bb6d58076e" + /// } + /// } + /// + /// ``` + /// + public func calcDeployAddress(sender: String, nonce: UInt64? = nil) -> Future { + return execAndConvert(in3: in3, method: "in3_calcDeployAddress", params:RPCObject( sender), nonce == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", nonce!) ), convertWith: toString ) + } + /// the Network Version (currently 1) /// - Returns: the Version number public func version() throws -> String { diff --git a/swift/Sources/In3/API/Zksync.swift b/swift/Sources/In3/API/Zksync.swift index f01955c42..283668bfa 100644 --- a/swift/Sources/In3/API/Zksync.swift +++ b/swift/Sources/In3/API/Zksync.swift @@ -25,7 +25,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).contractAddress() .observe(using: { + /// Zksync(in3).contractAddress() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -49,7 +49,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).tokens() .observe(using: { + /// Zksync(in3).tokens() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -92,7 +92,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).accountInfo() .observe(using: { + /// Zksync(in3).accountInfo() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -127,7 +127,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).txInfo(tx: "sync-tx:e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000") .observe(using: { + /// Zksync(in3).txInfo(tx: "sync-tx:e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -169,7 +169,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).setKey(token: "eth") .observe(using: { + /// Zksync(in3).setKey(token: "eth") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -192,7 +192,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// let result = try ZksyncAPI(in3).pubkeyhash() + /// let result = try Zksync(in3).pubkeyhash() /// // result = sync:4dcd9bb4463121470c7232efb9ff23ec21398e58 /// ``` /// @@ -209,7 +209,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// let result = try ZksyncAPI(in3).pubkey() + /// let result = try Zksync(in3).pubkey() /// // result = "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc04" /// ``` /// @@ -223,7 +223,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// let result = try ZksyncAPI(in3).accountAddress() + /// let result = try Zksync(in3).accountAddress() /// // result = "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" /// ``` /// @@ -246,7 +246,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).sign(message: "0xaabbccddeeff") .observe(using: { + /// Zksync(in3).sign(message: "0xaabbccddeeff") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -275,7 +275,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// let result = try ZksyncAPI(in3).verify(message: "0xaabbccddeeff", signature: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01") + /// let result = try Zksync(in3).verify(message: "0xaabbccddeeff", signature: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01") /// // result = 1 /// ``` /// @@ -296,7 +296,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).getTokenPrice(token: "WBTC") .observe(using: { + /// Zksync(in3).getTokenPrice(token: "WBTC") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -321,7 +321,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).getTxFee(txType: "Transfer", address: "0xabea9132b05a70803a4e85094fd0e1800777fbef", token: "BAT") .observe(using: { + /// Zksync(in3).getTxFee(txType: "Transfer", address: "0xabea9132b05a70803a4e85094fd0e1800777fbef", token: "BAT") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -349,7 +349,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).syncKey() .observe(using: { + /// Zksync(in3).syncKey() .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -375,7 +375,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).deposit(amount: 1000, token: "WBTC") .observe(using: { + /// Zksync(in3).deposit(amount: 1000, token: "WBTC") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -401,7 +401,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).transfer(to: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { + /// Zksync(in3).transfer(to: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -427,7 +427,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).withdraw(ethAddress: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { + /// Zksync(in3).withdraw(ethAddress: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -450,7 +450,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// ZksyncAPI(in3).emergencyWithdraw(token: "WBTC") .observe(using: { + /// Zksync(in3).emergencyWithdraw(token: "WBTC") .observe(using: { /// switch $0 { /// case let .failure(err): /// print("Failed because : \(err.localizedDescription)") @@ -498,7 +498,7 @@ public class Zksync { /// **Example** /// /// ```swift - /// let result = try ZksyncAPI(in3).aggregatePubkey(pubkeys: "0x0f61bfe164cc43b5a112bfbfb0583004e79dbfafc97a7daad14c5d511fea8e2435065ddd04329ec94be682bf004b03a5a4eeca9bf50a8b8b6023942adc0b3409") + /// let result = try Zksync(in3).aggregatePubkey(pubkeys: "0x0f61bfe164cc43b5a112bfbfb0583004e79dbfafc97a7daad14c5d511fea8e2435065ddd04329ec94be682bf004b03a5a4eeca9bf50a8b8b6023942adc0b3409") /// // result = "0x9ce5b6f8db3fbbe66a3bdbd3b4731f19ec27f80ee03ead3c0708798dd949882b" /// ``` /// @@ -524,10 +524,11 @@ public struct ZksyncContractAddress { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["govContract"] = RPCObject(govContract) - obj["mainContract"] = RPCObject(mainContract) + obj["govContract"] = RPCObject( govContract ) + obj["mainContract"] = RPCObject( mainContract ) return obj } + /// initialize the ZksyncContractAddress /// /// - Parameter govContract : the address of the govement contract @@ -562,12 +563,13 @@ public struct ZksyncTokens { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject(address) - obj["decimals"] = RPCObject(decimals) - obj["id"] = RPCObject(id) - obj["symbol"] = RPCObject(symbol) + obj["address"] = RPCObject( address ) + obj["decimals"] = RPCObject( String(format: "0x%1x", arguments: [decimals]) ) + obj["id"] = RPCObject( String(format: "0x%1x", arguments: [id]) ) + obj["symbol"] = RPCObject( symbol ) return obj } + /// initialize the ZksyncTokens /// /// - Parameter address : the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) @@ -610,10 +612,11 @@ public struct ZksyncAccountInfo { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject(address) - obj["id"] = RPCObject(id) + obj["address"] = RPCObject( address ) + obj["id"] = RPCObject( String(format: "0x%1x", arguments: [id]) ) return obj } + /// initialize the ZksyncAccountInfo /// /// - Parameter address : the address of the account @@ -650,10 +653,11 @@ public struct ZksyncCommited { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["nonce"] = RPCObject(nonce) - obj["pubKeyHash"] = RPCObject(pubKeyHash) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["pubKeyHash"] = RPCObject( pubKeyHash ) return obj } + /// initialize the ZksyncCommited /// /// - Parameter balances : the token-balance @@ -676,6 +680,7 @@ public struct ZksyncDepositing { balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) } + /// initialize the ZksyncDepositing /// /// - Parameter balances : the token-values. @@ -704,10 +709,11 @@ public struct ZksyncVerified { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["nonce"] = RPCObject(nonce) - obj["pubKeyHash"] = RPCObject(pubKeyHash) + obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) + obj["pubKeyHash"] = RPCObject( pubKeyHash ) return obj } + /// initialize the ZksyncVerified /// /// - Parameter balances : the token-balances. @@ -744,12 +750,13 @@ public struct ZksyncTxInfo { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["block"] = RPCObject(block) - obj["executed"] = RPCObject(executed) - obj["success"] = RPCObject(success) - obj["failReason"] = RPCObject(failReason) + obj["block"] = RPCObject( String(format: "0x%1x", arguments: [block]) ) + obj["executed"] = RPCObject( executed ) + obj["success"] = RPCObject( success ) + obj["failReason"] = RPCObject( failReason ) return obj } + /// initialize the ZksyncTxInfo /// /// - Parameter block : the blockNumber containing the tx or `null` if still pending @@ -796,14 +803,15 @@ public struct ZksyncTxFee { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["feeType"] = RPCObject(feeType) - obj["gasFee"] = RPCObject(gasFee) - obj["gasPriceWei"] = RPCObject(gasPriceWei) - obj["gasTxAmount"] = RPCObject(gasTxAmount) - obj["totalFee"] = RPCObject(totalFee) - obj["zkpFee"] = RPCObject(zkpFee) + obj["feeType"] = RPCObject( feeType ) + obj["gasFee"] = RPCObject( String(format: "0x%1x", arguments: [gasFee]) ) + obj["gasPriceWei"] = RPCObject( String(format: "0x%1x", arguments: [gasPriceWei]) ) + obj["gasTxAmount"] = RPCObject( String(format: "0x%1x", arguments: [gasTxAmount]) ) + obj["totalFee"] = RPCObject( String(format: "0x%1x", arguments: [totalFee]) ) + obj["zkpFee"] = RPCObject( String(format: "0x%1x", arguments: [zkpFee]) ) return obj } + /// initialize the ZksyncTxFee /// /// - Parameter feeType : Type of the transaaction @@ -831,7 +839,7 @@ public struct ZksyncTransactionReceipt { public var blockHash: String /// the deployed contract in case the tx did deploy a new contract - public var contractAddress: String + public var contractAddress: String? /// gas used for all transaction up to this one in the block public var cumulativeGasUsed: UInt64 @@ -840,7 +848,7 @@ public struct ZksyncTransactionReceipt { public var gasUsed: UInt64 /// array of events created during execution of the tx - public var logs: ZksyncLogs + public var logs: [ZksyncEthlog] /// bloomfilter used to detect events for `eth_getLogs` public var logsBloom: String @@ -858,10 +866,10 @@ public struct ZksyncTransactionReceipt { guard let obj = try toObject(rpc, optional) else { return nil } blockNumber = try toUInt64(obj["blockNumber"],false)! blockHash = try toString(obj["blockHash"],false)! - contractAddress = try toString(obj["contractAddress"],false)! + contractAddress = try toString(obj["contractAddress"],true)! cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! gasUsed = try toUInt64(obj["gasUsed"],false)! - logs = try ZksyncLogs(obj["logs"],false)! + logs = try toArray(obj["logs"])!.map({ try ZksyncEthlog($0,false)! }) logsBloom = try toString(obj["logsBloom"],false)! status = try toInt(obj["status"],false)! transactionHash = try toString(obj["transactionHash"],false)! @@ -870,17 +878,18 @@ public struct ZksyncTransactionReceipt { internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject(blockNumber) - obj["blockHash"] = RPCObject(blockHash) - obj["contractAddress"] = RPCObject(contractAddress) - obj["cumulativeGasUsed"] = RPCObject(cumulativeGasUsed) - obj["gasUsed"] = RPCObject(gasUsed) - obj["logsBloom"] = RPCObject(logsBloom) - obj["status"] = RPCObject(status) - obj["transactionHash"] = RPCObject(transactionHash) - obj["transactionIndex"] = RPCObject(transactionIndex) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + obj["blockHash"] = RPCObject( blockHash ) + if let x = contractAddress { obj["contractAddress"] = RPCObject( x ) } + obj["cumulativeGasUsed"] = RPCObject( String(format: "0x%1x", arguments: [cumulativeGasUsed]) ) + obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) + obj["logsBloom"] = RPCObject( logsBloom ) + obj["status"] = RPCObject( String(format: "0x%1x", arguments: [status]) ) + obj["transactionHash"] = RPCObject( transactionHash ) + obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) return obj } + /// initialize the ZksyncTransactionReceipt /// /// - Parameter blockNumber : the blockNumber @@ -893,7 +902,7 @@ public struct ZksyncTransactionReceipt { /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure /// - Parameter transactionHash : requested transactionHash /// - Parameter transactionIndex : transactionIndex within the containing block. - public init(blockNumber: UInt64, blockHash: String, contractAddress: String, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: ZksyncLogs, logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { + public init(blockNumber: UInt64, blockHash: String, contractAddress: String? = nil, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: [ZksyncEthlog], logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { self.blockNumber = blockNumber self.blockHash = blockHash self.contractAddress = contractAddress @@ -908,7 +917,7 @@ public struct ZksyncTransactionReceipt { } /// array of events created during execution of the tx -public struct ZksyncLogs { +public struct ZksyncEthlog { /// the address triggering the event. public var address: String @@ -937,10 +946,10 @@ public struct ZksyncLogs { public var transactionIndex: Int /// index of the event within the transaction. - public var transactionLogIndex: Int + public var transactionLogIndex: Int? /// mining-status - public var type: String + public var type: String? internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { guard let obj = try toObject(rpc, optional) else { return nil } @@ -953,25 +962,27 @@ public struct ZksyncLogs { topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) transactionHash = try toString(obj["transactionHash"],false)! transactionIndex = try toInt(obj["transactionIndex"],false)! - transactionLogIndex = try toInt(obj["transactionLogIndex"],false)! - type = try toString(obj["type"],false)! + transactionLogIndex = try toInt(obj["transactionLogIndex"],true)! + type = try toString(obj["type"],true)! } internal func toRPCDict() -> [String:RPCObject] { var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject(address) - obj["blockNumber"] = RPCObject(blockNumber) - obj["blockHash"] = RPCObject(blockHash) - obj["data"] = RPCObject(data) - obj["logIndex"] = RPCObject(logIndex) - obj["removed"] = RPCObject(removed) - obj["transactionHash"] = RPCObject(transactionHash) - obj["transactionIndex"] = RPCObject(transactionIndex) - obj["transactionLogIndex"] = RPCObject(transactionLogIndex) - obj["type"] = RPCObject(type) + obj["address"] = RPCObject( address ) + obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) + obj["blockHash"] = RPCObject( blockHash ) + obj["data"] = RPCObject( data ) + obj["logIndex"] = RPCObject( String(format: "0x%1x", arguments: [logIndex]) ) + obj["removed"] = RPCObject( removed ) + obj["topics"] = RPCObject( topics ) + obj["transactionHash"] = RPCObject( transactionHash ) + obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) + if let x = transactionLogIndex { obj["transactionLogIndex"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } + if let x = type { obj["type"] = RPCObject( x ) } return obj } - /// initialize the ZksyncLogs + + /// initialize the ZksyncEthlog /// /// - Parameter address : the address triggering the event. /// - Parameter blockNumber : the blockNumber @@ -984,7 +995,7 @@ public struct ZksyncLogs { /// - Parameter transactionIndex : transactionIndex within the containing block. /// - Parameter transactionLogIndex : index of the event within the transaction. /// - Parameter type : mining-status - public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int, type: String) { + public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int? = nil, type: String? = nil) { self.address = address self.blockNumber = blockNumber self.blockHash = blockHash diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift index cfe1105c8..cd50f338a 100644 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ b/swift/Sources/In3/Utils/JsonRpc.swift @@ -309,6 +309,7 @@ public enum RPCObject: Equatable { self = .string(value) } + /// Wrap a Integer as Value public init(_ value: Int) { self = .integer(value) @@ -339,6 +340,11 @@ public enum RPCObject: Equatable { self = .list(value.map { RPCObject($0) }) } + /// Wrap a String -Array as Value + public init(_ value: [String?]) { + self = .list(value.map { $0 == nil ? RPCObject.none : RPCObject($0!) }) + } + /// Wrap a Integer -Array as Value public init(_ value: [Int]) { self = .list(value.map { RPCObject($0) }) From ec0e12cea7e94b8edaf115357a43c4650123a2ad Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sun, 11 Apr 2021 19:23:29 +0200 Subject: [PATCH 117/221] added comments --- swift/Sources/In3/API/Contract.swift | 88 ++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/swift/Sources/In3/API/Contract.swift b/swift/Sources/In3/API/Contract.swift index 031cf0474..8feaa825e 100644 --- a/swift/Sources/In3/API/Contract.swift +++ b/swift/Sources/In3/API/Contract.swift @@ -31,13 +31,22 @@ internal func toHex(val:AnyObject, len:Int=0) -> String { return "0x" + s } +/// represents a contract with a defined ABI +/// for the ABI-spec see https://docs.soliditylang.org/en/v0.7.4/abi-spec.html?highlight=JSON#json public class Contract { var in3:In3 var address:String? var abi:[ABI] var hashes:[String:ABI] - + + /// creates a new Contract-Instance + /// you need to specify either the abi or the abiJson-Property. + /// - Parameter in3 : the Incubed instance + /// - Parameter abi : the parsed structuured ABI-Definitions + /// - Parameter abiJSON : the ABI as JSON-String + /// - Parameter at : address of the deployed contract + /// public init(in3:In3, abi:[ABI]? = nil, abiJSON:String? = nil, at: String?=nil) throws { self.in3=in3 self.address = at @@ -57,7 +66,15 @@ public class Contract { } } - public func deploy(data: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + /// deploys the contract and returns the transactionhash + /// - Parameter data : the bytes as hex of the code to deploy + /// - Parameter args : the optional arguments of the constructor + /// - Parameter account : the account to send the transaction from + /// - Parameter gas : the amount of gas to be used + /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. + /// + /// - Returns : The TransactionHash + public func deploy(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { do { return Eth(in3).sendTransaction(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)) } catch { @@ -67,7 +84,15 @@ public class Contract { } } - public func deployAndWait(data: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { + /// deploys the contract and wait until the receipt is available. + /// - Parameter data : the bytes as hex of the code to deploy + /// - Parameter args : the optional arguments of the constructor + /// - Parameter account : the account to send the transaction from + /// - Parameter gas : the amount of gas to be used + /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. + /// + /// - Returns : The TransactionReceipt + public func deployAndWait(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { do { return Eth(in3).sendTransactionAndWait(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)).chained(using: { self.address = $0.contractAddress @@ -80,6 +105,14 @@ public class Contract { } } + /// create a TransactionDefinition which cqan be used to deploy the contract + /// - Parameter data : the bytes as hex of the code to deploy + /// - Parameter args : the optional arguments of the constructor + /// - Parameter account : the account to send the transaction from + /// - Parameter gas : the amount of gas to be used + /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. + /// + /// - Returns : The Transaction Definition public func createDeployTx(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { if let x = args, x.count>0 { var tx = try createTx(name: "", args: x, account: account, gas: gas, gasPrice: gasPrice) @@ -90,6 +123,13 @@ public class Contract { } } + /// calls a function of the contract by running the code in a local evm. + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// - Parameter account : the account to be used as sender + /// - Parameter gas : the amount of gas to be used as limit + /// + /// - Returns : a array witht the return values of the function public func call(name: String, args: [AnyObject], block: UInt64? = nil, account:String?=nil, gas: UInt64?=nil) -> Future<[Any]> { do { let tx = try createTx(name: name, args: args, account: account, gas: gas) @@ -104,6 +144,12 @@ public class Contract { } } + /// estimates the gas used to send a transaction to the specified function of the contract. + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// - Parameter account : the account to be used as sender + /// + /// - Returns :the gas needed to run a tx public func estimateGas(name: String, args: [AnyObject], account:String?=nil) -> Future { do { let tx = try createTx(name: name, args: args, account: account) @@ -115,6 +161,14 @@ public class Contract { } } + /// sends a transaction to a function of the contract and returns the transactionHash + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// - Parameter account : the account to be used as sender + /// - Parameter gas : the amount of gas to be used as limit + /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. + /// + /// - Returns : the TransactionHash public func sendTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { do { return Eth(in3).sendTransaction(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) @@ -125,6 +179,14 @@ public class Contract { } } + /// sends a transaction to a function of the contract and waits for the receipt. + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// - Parameter account : the account to be used as sender + /// - Parameter gas : the amount of gas to be used as limit + /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. + /// + /// - Returns : the TransactionReceipt public func sendTxAndWait(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { do { return Eth(in3).sendTransactionAndWait(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) @@ -136,6 +198,10 @@ public class Contract { } /// returns the abi encoded arguments as hex string + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// + /// - Returns : the abi encoded arguments as hex string public func encodeCall(name: String, args: [AnyObject]) throws -> String{ if let abi = self[name] { return try Utils(in3).abiEncode(signature: abi.signature, params: args) @@ -145,6 +211,14 @@ public class Contract { } + /// creates the transaction parameter for a tx to the given function. + /// - Parameter name : the name of the function + /// - Parameter args : the arguments. + /// - Parameter account : the account to be used as sender + /// - Parameter gas : the amount of gas to be used as limit + /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. + /// + /// - Returns : the EthTransaction with the set parameters public func createTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { if let adr = address { let data = try encodeCall(name: name, args: args) @@ -156,6 +230,11 @@ public class Contract { /// reads events for the given contract /// if the eventName is omitted all events will be returned. ( in this case filter must be nil ! ) + /// - Parameter eventName : the name of the event or null if all events should be fetched + /// - Parameter filter : the dictionary with values to search for. Only valid if the eventName is set and the all values must be indexed arguments! + /// - Parameter fromBlock : the BlockNumber to start searching for events. If nil the latest block is used. + /// - Parameter toBlock : the BlockNumber to end searching for events. If nil the latest block is used. + /// - Parameter topics : the topics of the block as search criteria. public func getEvents(eventName:String? = nil, filter: [String:AnyObject]? = nil, fromBlock: UInt64? = nil, toBlock: UInt64? = nil, topics: [String?]?) -> Future<[EthEvent]> { do { var t = [String?].init(repeating: nil, count: 4) @@ -206,7 +285,8 @@ public class Contract { } - + /// accesses the ABI for the given function or event + /// - Parameter name : the name to search for subscript(name: String) -> ABI? { get { return self.abi.first(where:{ $0.name == name }) From dd00d4cb88c9707ba4d7af161b9b2e86b66954c4 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 12 Apr 2021 12:56:06 +0200 Subject: [PATCH 118/221] add tests to checkbinding --- scripts/check_bindings.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/check_bindings.js b/scripts/check_bindings.js index 57295c152..4f616b8bd 100755 --- a/scripts/check_bindings.js +++ b/scripts/check_bindings.js @@ -41,6 +41,11 @@ const bindings = { dotnet: strings('../dotnet/In3', '"', '*.cs'), swift: strings('../swift/Sources', '"'), c_api: strings('../c/src/api', '"',), + // test: [...strings('../c/test/testdata/requests', '"'), ...strings('../c/test/testdata/api', '"'), ...strings('../c/test/testdata/cmd', ' ')], + test: [ + ...strings('../c/test/testdata/requests', '"'), + ...strings('../c/test/testdata/api', '"'), + ...grep('\"^.*_.*\"', '../c/test/testdata/cmd').map(_ => ((/.* ([0-9a-zA-Z]+_[0-9a-zA-Z_]+).*/g).exec(_) || ['', ''])[1]).filter(_ => _)], autocmpl: grep("\"'.*?:\"", '_in3.sh').map(_ => ((/'([a-zA-Z0-9_]+):/gm).exec(_) || ["", ""])[1]), } const res = Object.keys(bindings).reduce((p, c) => ({ ...p, [c]: 0 }), {}) @@ -68,6 +73,7 @@ bindings.doc = grep('\"\\*\\*[a-zA-Z0-9_]+\\*\\*\"', '../../../doc/docs/rpc.md') bindings.wasm = grep('\"^[ ]*[a-zA-Z0-9_]+[\\?]*:.*\"', '../wasm/src').map(_ => lastToken(_.substring(0, _.lastIndexOf(':')).replace('?', '').trim())) bindings.autocmpl = [] bindings.c_api = [] +bindings.test = [] bindings.python = grep("\"self\\.[a-zA-Z0-9_]+\"", '../python/in3/model.py').map(_ => ((/self.([a-zA-Z0-9_]+)/gm).exec(_) || ["", ""])[1]) bindings.swift = grep("\"var [a-zA-Z0-9_]+\"", '../swift/Sources/In3/Config.swift').map(_ => ((/var ([a-zA-Z0-9_]+)/gm).exec(_) || ["", ""])[1]) From e657c79e3d73c8f8818f39293c79fb7b0e13b0e3 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 13 Apr 2021 19:38:54 +0200 Subject: [PATCH 119/221] define autoregister --- .gitignore | 1 + c/CMakeLists.txt | 9 +++ c/macro.cmake | 6 +- c/src/api/eth1/CMakeLists.txt | 1 + c/src/init/in3_init.c | 81 +------------------ c/src/nodeselect/full/CMakeLists.txt | 1 + c/src/pay/zksync/CMakeLists.txt | 3 +- .../signer/ledger-nano/signer/CMakeLists.txt | 2 +- c/src/signer/pk-signer/CMakeLists.txt | 3 +- c/src/tools/clientdata/CMakeLists.txt | 3 +- c/src/tools/sentry/CMakeLists.txt | 1 + c/src/tools/swift/CMakeLists.txt | 8 +- c/src/transport/curl/CMakeLists.txt | 3 +- c/src/transport/http/CMakeLists.txt | 3 +- c/src/transport/winhttp/CMakeLists.txt | 3 +- c/src/verifier/btc/CMakeLists.txt | 3 +- c/src/verifier/eth1/basic/CMakeLists.txt | 1 + c/src/verifier/eth1/full/CMakeLists.txt | 3 +- c/src/verifier/eth1/nano/CMakeLists.txt | 3 +- c/src/verifier/ipfs/CMakeLists.txt | 3 +- 20 files changed, 47 insertions(+), 94 deletions(-) diff --git a/.gitignore b/.gitignore index cb5a6ac5e..8a32b0f8e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ coverage_report test/bindings/wasm/node_modules/ **/node_modules/ **/package-lock.json +c/src/init/autoregister.h Testing* wasm/test/in3 .in3 diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 367befaa9..9306cc118 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -74,6 +74,15 @@ add_subdirectory(src/tools) add_subdirectory(src/nodeselect) add_subdirectory(docs) +# generate the init-module +get_property(modules GLOBAL PROPERTY IN3_REGISTERS) +foreach(m IN LISTS modules) + set(REGISTER_DEF "${REGISTER_DEF}in3_ret_t ${m} (in3_t*);\n") + set(REGISTER_CALL "${REGISTER_CALL} in3_register_default(${m});\n") +endforeach() +file(WRITE src/init/autoregister.h "${REGISTER_DEF}\n\nstatic void auto_init() {\n${REGISTER_CALL}}\n") + +# define lib dir link_directories(${CMAKE_BINARY_DIR}/lib/) # create the library diff --git a/c/macro.cmake b/c/macro.cmake index aea814037..c6f56ab34 100644 --- a/c/macro.cmake +++ b/c/macro.cmake @@ -1,6 +1,6 @@ macro(add_static_library ) - cmake_parse_arguments(_LIB "" NAME "SOURCES;DEPENDS" ${ARGN} ) + cmake_parse_arguments(_LIB "" "NAME;REGISTER" "SOURCES;DEPENDS" ${ARGN} ) # create objects add_library(${_LIB_NAME}_o OBJECT ${_LIB_SOURCES}) @@ -12,4 +12,8 @@ macro(add_static_library ) target_link_libraries(${_LIB_NAME} ${_LIB_DEPENDS}) get_property(tmp GLOBAL PROPERTY IN3_OBJECTS) set_property(GLOBAL PROPERTY IN3_OBJECTS ${tmp} $) + if(_LIB_REGISTER) + get_property(tmp GLOBAL PROPERTY IN3_REGISTERS) + set_property(GLOBAL PROPERTY IN3_REGISTERS ${tmp} ${_LIB_REGISTER}) + endif(_LIB_REGISTER) endmacro() diff --git a/c/src/api/eth1/CMakeLists.txt b/c/src/api/eth1/CMakeLists.txt index ea3923163..12773519a 100644 --- a/c/src/api/eth1/CMakeLists.txt +++ b/c/src/api/eth1/CMakeLists.txt @@ -45,6 +45,7 @@ endif() add_static_library( NAME eth_api + REGISTER in3_register_eth_api SOURCES eth_api.c diff --git a/c/src/init/in3_init.c b/c/src/init/in3_init.c index b0ae5338d..35b8767c3 100644 --- a/c/src/init/in3_init.c +++ b/c/src/init/in3_init.c @@ -1,88 +1,15 @@ #include "in3_init.h" -#include "../api/eth1/eth_api.h" #include "../core/client/plugin.h" -#include "../pay/eth/pay_eth.h" -#include "../pay/zksync/zksync.h" -#include "../signer/pk-signer/signer.h" -#include "../third-party/zkcrypto/lib.h" -#ifdef USE_CURL -#include "../transport/curl/in3_curl.h" -#elif USE_WINHTTP -#include "../transport/winhttp/in3_winhttp.h" -#else -#include "../transport/http/in3_http.h" -#endif -#ifdef NODESELECT_DEF -#include "../nodeselect/full/nodeselect_def.h" -#endif -#include "../verifier/btc/btc.h" -#include "../verifier/eth1/basic/eth_basic.h" -#include "../verifier/eth1/full/eth_full.h" -#include "../verifier/eth1/nano/eth_nano.h" -#include "../verifier/ipfs/ipfs.h" -#ifdef SENTRY -#include "../tools/sentry/sentry.h" -#endif - -static bool initialized; - -static void init_verifier() { -#ifdef ETH_FULL - in3_register_default(in3_register_eth_full); -#endif -#ifdef ETH_BASIC - in3_register_default(in3_register_eth_basic); -#endif -#ifdef ETH_NANO - in3_register_default(in3_register_eth_nano); -#endif -#ifdef ETH_API - in3_register_default(in3_register_eth_api); -#endif -#ifdef IPFS - in3_register_default(in3_register_ipfs); -#endif -#ifdef BTC - in3_register_default(in3_register_btc); -#endif -#ifdef PAY_ETH - in3_register_default(in3_register_pay_eth); -#endif -#ifdef ZKSYNC - in3_register_default(in3_register_zksync); -#endif -#ifdef SENTRY - in3_register_default(in3_register_sentry); -#endif -#ifdef PK_SIGNER - in3_register_default(eth_register_pk_signer); -#endif -} +#include "autoregister.h" -static void init_transport() { -#ifdef TRANSPORTS -#ifdef USE_CURL - in3_register_default(in3_register_curl); -#elif USE_WINHTTP - in3_register_default(in3_register_winhttp); -#else - in3_register_default(in3_register_http); -#endif /* USE_CURL */ -#endif /* TRANSPORTS */ -} +void zkcrypto_initialize(); -static void init_nodeselect() { -#ifdef NODESELECT_DEF - in3_register_default(in3_register_nodeselect_def); -#endif -} +static bool initialized; void in3_init() { if (!initialized) { initialized = true; - init_transport(); - init_verifier(); - init_nodeselect(); + auto_init(); #ifdef ZKSYNC zkcrypto_initialize(); #endif diff --git a/c/src/nodeselect/full/CMakeLists.txt b/c/src/nodeselect/full/CMakeLists.txt index 9c3fea64d..1a42b85fc 100644 --- a/c/src/nodeselect/full/CMakeLists.txt +++ b/c/src/nodeselect/full/CMakeLists.txt @@ -35,6 +35,7 @@ add_static_library( NAME nodeselect_def + REGISTER in3_register_nodeselect_def SOURCES nodeselect_def.c diff --git a/c/src/pay/zksync/CMakeLists.txt b/c/src/pay/zksync/CMakeLists.txt index 95eb4efee..b7a93ae26 100644 --- a/c/src/pay/zksync/CMakeLists.txt +++ b/c/src/pay/zksync/CMakeLists.txt @@ -35,7 +35,8 @@ add_static_library( NAME zksync - + REGISTER in3_register_zksync + SOURCES zksync.c zk_message.c diff --git a/c/src/signer/ledger-nano/signer/CMakeLists.txt b/c/src/signer/ledger-nano/signer/CMakeLists.txt index 8d08d39c2..e2b04f2dc 100644 --- a/c/src/signer/ledger-nano/signer/CMakeLists.txt +++ b/c/src/signer/ledger-nano/signer/CMakeLists.txt @@ -40,7 +40,7 @@ endif() add_static_library( NAME ledger_signer - + SOURCES ledger_signer.c device_apdu_commands.c diff --git a/c/src/signer/pk-signer/CMakeLists.txt b/c/src/signer/pk-signer/CMakeLists.txt index 73d80492b..2f3cb6b3a 100644 --- a/c/src/signer/pk-signer/CMakeLists.txt +++ b/c/src/signer/pk-signer/CMakeLists.txt @@ -35,7 +35,8 @@ add_static_library( NAME pk_signer - + REGISTER eth_register_pk_signer + SOURCES signer.c diff --git a/c/src/tools/clientdata/CMakeLists.txt b/c/src/tools/clientdata/CMakeLists.txt index a17418a56..ff84ed2fe 100644 --- a/c/src/tools/clientdata/CMakeLists.txt +++ b/c/src/tools/clientdata/CMakeLists.txt @@ -33,8 +33,7 @@ ############################################################################### add_static_library( - NAME - plugin_client_data + NAME plugin_client_data SOURCES client_data.c diff --git a/c/src/tools/sentry/CMakeLists.txt b/c/src/tools/sentry/CMakeLists.txt index d6ece783d..6fa78a6aa 100644 --- a/c/src/tools/sentry/CMakeLists.txt +++ b/c/src/tools/sentry/CMakeLists.txt @@ -35,6 +35,7 @@ add_static_library( NAME in3_sentry + REGISTER in3_register_sentry SOURCES sentry.c DEPENDS diff --git a/c/src/tools/swift/CMakeLists.txt b/c/src/tools/swift/CMakeLists.txt index e04f9a6a5..01e825327 100644 --- a/c/src/tools/swift/CMakeLists.txt +++ b/c/src/tools/swift/CMakeLists.txt @@ -33,12 +33,12 @@ ############################################################################### add_static_library( - NAME - in3_swift + NAME in3_swift + REGISTER in3_register_swift SOURCES - swift.c + swift.c DEPENDS - core + core ) diff --git a/c/src/transport/curl/CMakeLists.txt b/c/src/transport/curl/CMakeLists.txt index 60069bea5..8ddc9b1d8 100644 --- a/c/src/transport/curl/CMakeLists.txt +++ b/c/src/transport/curl/CMakeLists.txt @@ -100,7 +100,8 @@ endif () # add lib add_static_library( NAME transport_curl - + REGISTER in3_register_curl + SOURCES in3_curl.c diff --git a/c/src/transport/http/CMakeLists.txt b/c/src/transport/http/CMakeLists.txt index 9f0c32189..34b142fa9 100644 --- a/c/src/transport/http/CMakeLists.txt +++ b/c/src/transport/http/CMakeLists.txt @@ -35,7 +35,8 @@ # add lib add_static_library( NAME transport_http - + REGISTER in3_register_http + SOURCES in3_http.c diff --git a/c/src/transport/winhttp/CMakeLists.txt b/c/src/transport/winhttp/CMakeLists.txt index a166d33e3..680dafd9c 100644 --- a/c/src/transport/winhttp/CMakeLists.txt +++ b/c/src/transport/winhttp/CMakeLists.txt @@ -35,7 +35,8 @@ # add lib add_static_library( NAME transport_winhttp - + REGISTER in3_register_winhttp + SOURCES in3_winhttp.c diff --git a/c/src/verifier/btc/CMakeLists.txt b/c/src/verifier/btc/CMakeLists.txt index 5193471f8..381b53572 100644 --- a/c/src/verifier/btc/CMakeLists.txt +++ b/c/src/verifier/btc/CMakeLists.txt @@ -34,7 +34,8 @@ add_static_library( NAME btc - + REGISTER in3_register_btc + SOURCES btc_merkle.c btc_types.c diff --git a/c/src/verifier/eth1/basic/CMakeLists.txt b/c/src/verifier/eth1/basic/CMakeLists.txt index 1e3ef01f5..46f284f05 100644 --- a/c/src/verifier/eth1/basic/CMakeLists.txt +++ b/c/src/verifier/eth1/basic/CMakeLists.txt @@ -34,6 +34,7 @@ add_static_library( NAME eth_basic + REGISTER in3_register_eth_basic SOURCES eth_basic.c diff --git a/c/src/verifier/eth1/full/CMakeLists.txt b/c/src/verifier/eth1/full/CMakeLists.txt index d20276eb8..e18f3aadb 100644 --- a/c/src/verifier/eth1/full/CMakeLists.txt +++ b/c/src/verifier/eth1/full/CMakeLists.txt @@ -35,7 +35,8 @@ add_static_library( NAME eth_full - + REGISTER in3_register_eth_full + SOURCES eth_full.c diff --git a/c/src/verifier/eth1/nano/CMakeLists.txt b/c/src/verifier/eth1/nano/CMakeLists.txt index 6e52a5c9e..67d9a3dcc 100644 --- a/c/src/verifier/eth1/nano/CMakeLists.txt +++ b/c/src/verifier/eth1/nano/CMakeLists.txt @@ -34,7 +34,8 @@ add_static_library( NAME eth_nano - + REGISTER in3_register_eth_nano + SOURCES eth_nano.c rlp.c diff --git a/c/src/verifier/ipfs/CMakeLists.txt b/c/src/verifier/ipfs/CMakeLists.txt index 7cf109ab9..e34a2a789 100644 --- a/c/src/verifier/ipfs/CMakeLists.txt +++ b/c/src/verifier/ipfs/CMakeLists.txt @@ -35,7 +35,8 @@ add_static_library( NAME ipfs - + REGISTER in3_register_ipfs + SOURCES ipfs.c ipfs.pb.c From 6b1b1c1e230a7cf399c66877d289acabbeeba380 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 13 Apr 2021 21:34:32 +0200 Subject: [PATCH 120/221] moved TRY_RPC and added cmake magic --- c/include/in3/utils.h | 5 +++++ c/macro.cmake | 31 ++++++++++++++++++------------- c/src/core/util/debug.h | 6 +----- c/src/core/util/utils.h | 5 +++++ 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/c/include/in3/utils.h b/c/include/in3/utils.h index 9f6a71cf8..328134038 100644 --- a/c/include/in3/utils.h +++ b/c/include/in3/utils.h @@ -224,6 +224,11 @@ uint64_t current_ms(); return _r; \ } \ } +#define TRY_RPC(name, fn) \ + if (strcmp(ctx->method, name) == 0) return fn; +/** used in if-conditions and returns true if the vc->method mathes the name. It is also used as marker.*/ +#define VERIFY_RPC(name) (strcmp(vc->method, name) == 0) +#define CONFIG_KEY(name) key(name) /** * executes the expression and expects value to equal val. diff --git a/c/macro.cmake b/c/macro.cmake index c6f56ab34..0413cc2ed 100644 --- a/c/macro.cmake +++ b/c/macro.cmake @@ -1,19 +1,24 @@ macro(add_static_library ) cmake_parse_arguments(_LIB "" "NAME;REGISTER" "SOURCES;DEPENDS" ${ARGN} ) + string(TOUPPER "MOD_${_LIB_NAME}" tmp) + option(${tmp} "module ${_LIB_NAME}" ON) + if (${${tmp}}) + # create objects + add_library(${_LIB_NAME}_o OBJECT ${_LIB_SOURCES}) - # create objects - add_library(${_LIB_NAME}_o OBJECT ${_LIB_SOURCES}) + # add dependency + add_library(${_LIB_NAME} STATIC $) - # add dependency - add_library(${_LIB_NAME} STATIC $) - - target_compile_definitions(${_LIB_NAME}_o PRIVATE) - target_link_libraries(${_LIB_NAME} ${_LIB_DEPENDS}) - get_property(tmp GLOBAL PROPERTY IN3_OBJECTS) - set_property(GLOBAL PROPERTY IN3_OBJECTS ${tmp} $) - if(_LIB_REGISTER) - get_property(tmp GLOBAL PROPERTY IN3_REGISTERS) - set_property(GLOBAL PROPERTY IN3_REGISTERS ${tmp} ${_LIB_REGISTER}) - endif(_LIB_REGISTER) + target_compile_definitions(${_LIB_NAME}_o PRIVATE) + target_link_libraries(${_LIB_NAME} ${_LIB_DEPENDS}) + get_property(tmp GLOBAL PROPERTY IN3_OBJECTS) + set_property(GLOBAL PROPERTY IN3_OBJECTS ${tmp} $) + get_property(tmp GLOBAL PROPERTY IN3_API_NAMES) + set_property(GLOBAL PROPERTY IN3_API_NAMES ${tmp} ${_LIB_NAME}) + if(_LIB_REGISTER) + get_property(tmp GLOBAL PROPERTY IN3_REGISTERS) + set_property(GLOBAL PROPERTY IN3_REGISTERS ${tmp} ${_LIB_REGISTER}) + endif(_LIB_REGISTER) + endif() endmacro() diff --git a/c/src/core/util/debug.h b/c/src/core/util/debug.h index 0ba213e51..6009055e1 100644 --- a/c/src/core/util/debug.h +++ b/c/src/core/util/debug.h @@ -174,9 +174,5 @@ static inline void add_hex(sb_t* sb, char prefix, const char* property, bytes_t } /** used for exeuting a function based on the name. This macro will return if the name matches. */ -#define TRY_RPC(name, fn) \ - if (strcmp(ctx->method, name) == 0) return fn; -/** used in if-conditions and returns true if the vc->method mathes the name. It is also used as marker.*/ -#define VERIFY_RPC(name) (strcmp(vc->method, name) == 0) -#define CONFIG_KEY(name) key(name) + #endif /* DEBUG_H */ \ No newline at end of file diff --git a/c/src/core/util/utils.h b/c/src/core/util/utils.h index 9f6a71cf8..328134038 100644 --- a/c/src/core/util/utils.h +++ b/c/src/core/util/utils.h @@ -224,6 +224,11 @@ uint64_t current_ms(); return _r; \ } \ } +#define TRY_RPC(name, fn) \ + if (strcmp(ctx->method, name) == 0) return fn; +/** used in if-conditions and returns true if the vc->method mathes the name. It is also used as marker.*/ +#define VERIFY_RPC(name) (strcmp(vc->method, name) == 0) +#define CONFIG_KEY(name) key(name) /** * executes the expression and expects value to equal val. From ddb2897cc3ea877f0bbf996452c292206711245c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 13 Apr 2021 21:39:03 +0200 Subject: [PATCH 121/221] fix swift --- c/src/tools/swift/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/c/src/tools/swift/CMakeLists.txt b/c/src/tools/swift/CMakeLists.txt index 01e825327..508c6cd4f 100644 --- a/c/src/tools/swift/CMakeLists.txt +++ b/c/src/tools/swift/CMakeLists.txt @@ -34,7 +34,6 @@ add_static_library( NAME in3_swift - REGISTER in3_register_swift SOURCES swift.c From 3b045ad9c1d42e25086952d7370ea6601966ce34 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 13 Apr 2021 22:10:52 +0200 Subject: [PATCH 122/221] fix quemu tests --- c/include/in3/nodelist.h | 322 +++++++++++++++++++++++++ c/include/in3/nodeselect_def.h | 34 +++ c/src/nodeselect/full/nodeselect_def.h | 4 + c/test/qemu/esp32/main/CMakeLists.txt | 2 - c/test/qemu/esp32/main/in3_main.c | 18 +- c/test/qemu/zephyr-arm3/CMakeLists.txt | 1 - c/test/qemu/zephyr-arm3/src/main.c | 4 +- 7 files changed, 373 insertions(+), 12 deletions(-) create mode 100644 c/include/in3/nodelist.h create mode 100644 c/include/in3/nodeselect_def.h diff --git a/c/include/in3/nodelist.h b/c/include/in3/nodelist.h new file mode 100644 index 000000000..1db00b740 --- /dev/null +++ b/c/include/in3/nodelist.h @@ -0,0 +1,322 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +/** + * handles nodelists. + * + * */ + +#include "client.h" +#include "request.h" +#include "log.h" +#include "mem.h" +#include + +#ifndef NODELIST_H +#define NODELIST_H + +#ifdef THREADSAFE +#if defined(_MSC_VER) || defined(__MINGW32__) +#include +typedef HANDLE in3_mutex_t; +#define MUTEX_INIT(mutex) mutex = CreateMutex(NULL, FALSE, NULL); +#define MUTEX_LOCK(mutex) WaitForSingleObject(mutex, INFINITE); +#define MUTEX_UNLOCK(mutex) ReleaseMutex(mutex); +#define MUTEX_FREE(mutex) CloseHandle(mutex); +#else +#include +typedef pthread_mutex_t in3_mutex_t; +#define MUTEX_INIT(mutex) \ + { \ + pthread_mutexattr_t attr; \ + pthread_mutexattr_init(&attr); \ + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ + pthread_mutex_init(&(mutex), &attr); \ + } +#define MUTEX_LOCK(mutex) pthread_mutex_lock(&(mutex)); +#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&(mutex)); +#define MUTEX_FREE(mutex) pthread_mutex_destroy(&(mutex)); +#endif +#endif + +/** + * a list of node attributes (mostly used internally) + */ +typedef enum { + ATTR_WHITELISTED = 1, /**< indicates if node exists in whiteList */ + ATTR_BOOT_NODE = 2, /**< used to avoid filtering manually added nodes before first nodeList update */ +} in3_node_attr_type_t; + +/** incubed node-configuration. + * + * These information are read from the Registry contract and stored in this struct representing a server or node. + */ +typedef struct in3_node { + address_t address; /**< address of the server */ + bool blocked; /**< if true this node has been blocked for sending wrong responses */ + uint_fast16_t index; /**< index within the nodelist, also used in the contract as key */ + uint_fast16_t capacity; /**< the maximal capacity able to handle */ + uint64_t deposit; /**< the deposit stored in the registry contract, which this would lose if it sends a wrong blockhash */ + in3_node_props_t props; /**< used to identify the capabilities of the node. See in3_node_props_type_t in nodelist.h */ + char* url; /**< the url of the node */ + uint_fast8_t attrs; /**< bitmask of internal attributes */ +} in3_node_t; + +/** + * Weight or reputation of a node. + * + * Based on the past performance of the node a weight is calculated given faster nodes a higher weight + * and chance when selecting the next node from the nodelist. + * These weights will also be stored in the cache (if available) + */ +typedef struct in3_node_weight { + uint32_t response_count; /**< counter for responses */ + uint32_t total_response_time; /**< total of all response times */ + uint64_t blacklisted_until; /**< if >0 this node is blacklisted until k. k is a unix timestamp */ +} in3_node_weight_t; + +/** + * defines a whitelist structure used for the nodelist. + */ +typedef struct in3_whitelist { + bool needs_update; /**< if true the nodelist should be updated and will trigger a `in3_nodeList`-request before the next request is send. */ + uint64_t last_block; /**< last blocknumber the whiteList was updated, which is used to detect changed in the whitelist */ + address_t contract; /**< address of whiteList contract. If specified, whiteList is always auto-updated and manual whiteList is overridden */ + bytes_t addresses; /**< serialized list of node addresses that constitute the whiteList */ +} in3_whitelist_t; + +typedef enum { + NODE_PROP_PROOF = 0x1, /**< filter out nodes which are providing no proof */ + NODE_PROP_MULTICHAIN = 0x2, /**< filter out nodes other then which have capability of the same RPC endpoint may also accept requests for different chains */ + NODE_PROP_ARCHIVE = 0x4, /**< filter out non-archive supporting nodes */ + NODE_PROP_HTTP = 0x8, /**< filter out non-http nodes */ + NODE_PROP_BINARY = 0x10, /**< filter out nodes that don't support binary encoding */ + NODE_PROP_ONION = 0x20, /**< filter out non-onion nodes */ + NODE_PROP_SIGNER = 0x40, /**< filter out non-signer nodes */ + NODE_PROP_DATA = 0x80, /**< filter out non-data provider nodes */ + NODE_PROP_STATS = 0x100, /**< filter out nodes that do not provide stats */ + NODE_PROP_MIN_BLOCK_HEIGHT = 0x400, /**< filter out nodes that will sign blocks with lower min block height than specified */ +} in3_node_props_type_t; + +typedef struct { + in3_node_props_t props; + d_token_t* nodes; + node_match_t* exclusions; +} in3_node_filter_t; + +typedef struct node_offline_ { + in3_node_t* offline; + address_t reporter; + struct node_offline_* next; +} node_offline_t; + +typedef struct in3_nodeselect_def { + bool dirty; /**< indicates whether the nodelist has been modified after last read from cache */ + uint16_t avg_block_time; /**< average block time (seconds) for this data (calculated internally) */ + unsigned int nodelist_length; /**< number of nodes in the nodeList */ + uint64_t last_block; /**< last blocknumber the nodeList was updated, which is used to detect changed in the nodelist*/ + address_t contract; /**< the address of the registry contract */ + bytes32_t registry_id; /**< the identifier of the registry */ + in3_node_t* nodelist; /**< array of nodes */ + in3_node_weight_t* weights; /**< stats and weights recorded for each node */ + bytes_t** init_addresses; /**< array of addresses of nodes that should always part of the nodeList */ + node_offline_t* offlines; /**< linked-list of offline nodes */ + +#ifdef NODESELECT_DEF_WL + in3_whitelist_t* whitelist; /**< if set the whitelist of the addresses. */ +#endif + + struct { + uint64_t exp_last_block; /**< the last_block when the nodelist last changed reported by this node */ + uint64_t timestamp; /**< approx. time when nodelist must be updated (i.e. when reported last_block will be considered final) */ + address_t node; /**< node that reported the last_block which necessitated a nodeList update */ + } * nodelist_upd8_params; + + chain_id_t chain_id; /**< the chain_id of the data */ + struct in3_nodeselect_def* next; /**< the next in the linked list */ + uint32_t ref_counter; /**< number of client using this nodelist */ + bytes_t* pre_address_filter; /**< addresses of allowed list (usually because those nodes where paid for) */ + +#ifdef THREADSAFE + in3_mutex_t mutex; /**< mutex to lock this nodelist */ +#endif +} in3_nodeselect_def_t; + +/** config for each client pointing to the global data*/ +typedef struct in3_nodeselect_config { + in3_nodeselect_def_t* data; /**< points to the global nodelist data*/ + in3_node_props_t node_props; /**< used to identify the capabilities of the node. */ + uint64_t min_deposit; /**< min stake of the server. Only nodes owning at least this amount will be chosen. */ + uint16_t node_limit; /**< the limit of nodes to store in the client. */ + uint8_t request_count; /**< the number of request send when getting a first answer */ +} in3_nodeselect_config_t; + +/** returns the nodelistwrapper.*/ +NONULL in3_nodeselect_config_t* in3_get_nodelist(in3_t* c); + +/** removes all nodes and their weights from the nodelist */ +NONULL void in3_nodelist_clear(in3_nodeselect_def_t* data); + +#ifdef NODESELECT_DEF_WL +/** removes all nodes and their weights from the nodelist */ +NONULL void in3_whitelist_clear(in3_whitelist_t* data); + +/** updates all whitelisted flags in the nodelist */ +NONULL void in3_client_run_chain_whitelisting(in3_nodeselect_def_t* data); +#endif + +/** check if the nodelist is up to date. + * + * if not it will fetch a new version first (if the needs_update-flag is set). + */ +NONULL in3_ret_t in3_node_list_get(in3_req_t* req, in3_nodeselect_def_t* data, bool update, in3_node_t** nodelist, unsigned int* nodelist_length, in3_node_weight_t** weights); + +/** + * filters and fills the weights on a returned linked list. + */ +NONULL_FOR((1, 2, 3, 4, 7, 8)) +node_match_t* in3_node_list_fill_weight(in3_t* c, in3_nodeselect_config_t* w, in3_node_t* all_nodes, in3_node_weight_t* weights, unsigned int len, uint64_t now, uint32_t* total_weight, unsigned int* total_found, const in3_node_filter_t* filter, bytes_t* pre_filter); + +/** + * calculates the weight for a node. + */ +NONULL uint32_t in3_node_calculate_weight(in3_node_weight_t* n, uint32_t capa, uint64_t now); +/** + * picks (based on the config) a random number of nodes and returns them as weightslist. + */ +NONULL_FOR((1, 2, 3)) +in3_ret_t in3_node_list_pick_nodes(in3_req_t* req, in3_nodeselect_config_t* w, node_match_t** nodes, unsigned int request_count, const in3_node_filter_t* filter); + +/** + * forces the client to update the nodelist + */ +in3_ret_t update_nodes(in3_t* c, in3_nodeselect_def_t* data); + +#define NODE_FILTER_INIT \ + (in3_node_filter_t) { .props = 0, .nodes = NULL } + +/** + * Initializer for in3_node_props_t + */ +#define in3_node_props_init(np) *(np) = 0 + +/** + * setter method for interacting with in3_node_props_t. + */ +NONULL void in3_node_props_set(in3_node_props_t* node_props, /**< pointer to the properties to change */ + in3_node_props_type_t type, /**< key or type of the property */ + uint8_t value /**< value to set */ +); + +/** + * returns the value of the specified property-type. + * @return value as a number + */ +static inline uint32_t in3_node_props_get(in3_node_props_t np, /**< property to read from */ + in3_node_props_type_t t) { /**< the value to extract */ + return ((t == NODE_PROP_MIN_BLOCK_HEIGHT) ? ((np >> 32U) & 0xFFU) : !!(np & t)); +} + +/** + * checks if the given type is set in the properties + * @return true if set + */ +static inline bool in3_node_props_matches(in3_node_props_t np, /**< property to read from */ + in3_node_props_type_t t) { /**< the value to extract */ + return !!(np & t); +} + +NONULL static inline bool nodelist_first_upd8(const in3_nodeselect_def_t* data) { + return (data->nodelist_upd8_params != NULL && data->nodelist_upd8_params->exp_last_block == 0); +} + +NONULL static inline bool nodelist_not_first_upd8(const in3_nodeselect_def_t* data) { + return (data->nodelist_upd8_params != NULL && data->nodelist_upd8_params->exp_last_block != 0); +} + +NONULL static inline in3_node_t* get_node_idx(const in3_nodeselect_def_t* data, unsigned int index) { + return index < data->nodelist_length ? data->nodelist + index : NULL; +} + +NONULL static inline in3_node_weight_t* get_node_weight_idx(const in3_nodeselect_def_t* data, unsigned int index) { + return index < data->nodelist_length ? data->weights + index : NULL; +} + +static inline in3_node_t* get_node(const in3_nodeselect_def_t* data, const node_match_t* node) { + return node ? get_node_idx(data, node->index) : NULL; +} + +NONULL static inline in3_node_weight_t* get_node_weight(const in3_nodeselect_def_t* data, const node_match_t* node) { + return node ? get_node_weight_idx(data, node->index) : NULL; +} + +static inline bool is_blacklisted(const in3_node_t* node) { return node && node->blocked; } + +NONULL static in3_ret_t blacklist_node(in3_nodeselect_def_t* data, unsigned int index, uint64_t secs_from_now) { + in3_node_t* node = get_node_idx(data, index); + if (is_blacklisted(node)) return IN3_ERPC; // already handled + + if (node && !node->blocked) { + in3_node_weight_t* w = get_node_weight_idx(data, index); + if (!w) { + in3_log_debug("failed to blacklist node: %s\n", node->url); + return IN3_EFIND; + } + + // blacklist the node + uint64_t blacklisted_until_ = in3_time(NULL) + secs_from_now; + if (w->blacklisted_until != blacklisted_until_) + data->dirty = true; + w->blacklisted_until = blacklisted_until_; + node->blocked = true; + in3_log_debug("Blacklisting node for unverifiable response: %s\n", node ? node->url : ""); + } + return IN3_OK; +} + +NONULL static inline in3_ret_t blacklist_node_addr(in3_nodeselect_def_t* data, const address_t node_addr, uint64_t secs_from_now) { + for (unsigned int i = 0; i < data->nodelist_length; ++i) + if (!memcmp(data->nodelist[i].address, node_addr, 20)) + return blacklist_node(data, data->nodelist[i].index, secs_from_now); + return IN3_OK; +} + +NONULL static inline in3_ret_t blacklist_node_url(in3_nodeselect_def_t* data, const char* node_url, uint64_t secs_from_now) { + for (unsigned int i = 0; i < data->nodelist_length; ++i) + if (!strcmp(data->nodelist[i].url, node_url)) + return blacklist_node(data, data->nodelist[i].index, secs_from_now); + return IN3_OK; +} + +#endif diff --git a/c/include/in3/nodeselect_def.h b/c/include/in3/nodeselect_def.h new file mode 100644 index 000000000..5b1214e59 --- /dev/null +++ b/c/include/in3/nodeselect_def.h @@ -0,0 +1,34 @@ +/** + * + */ +// @PUBLIC_HEADER +#ifndef IN3_NODE_SELECT_DEF_H +#define IN3_NODE_SELECT_DEF_H + +#include "plugin.h" +#include "request.h" +#include "nodelist.h" + +#ifdef NODESELECT_DEF + +/** + * default nodeselect implementation + */ +in3_ret_t in3_nodeselect_handle_action(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx); + +/** + * get access to internal plugin data if registered + */ +static inline in3_nodeselect_def_t* in3_nodeselect_def_data(in3_t* c) { + in3_nodeselect_config_t* w = in3_plugin_get_data(c, in3_nodeselect_handle_action); + return w ? w->data : NULL; +} + +/** + * registers the default nodeselect implementation + */ +in3_ret_t in3_register_nodeselect_def(in3_t* c); + +#endif //NODESELECT_DEF + +#endif //IN3_NODE_SELECT_DEF_H diff --git a/c/src/nodeselect/full/nodeselect_def.h b/c/src/nodeselect/full/nodeselect_def.h index 8326ed346..390f7455f 100644 --- a/c/src/nodeselect/full/nodeselect_def.h +++ b/c/src/nodeselect/full/nodeselect_def.h @@ -1,3 +1,7 @@ +/** + * + */ +// @PUBLIC_HEADER #ifndef IN3_NODE_SELECT_DEF_H #define IN3_NODE_SELECT_DEF_H diff --git a/c/test/qemu/esp32/main/CMakeLists.txt b/c/test/qemu/esp32/main/CMakeLists.txt index ca59e5e76..f15b3f30c 100644 --- a/c/test/qemu/esp32/main/CMakeLists.txt +++ b/c/test/qemu/esp32/main/CMakeLists.txt @@ -21,7 +21,6 @@ OPTION(ESP_IDF "Esp-idf framework" ON) ADD_DEFINITIONS(-DIN3_MATH_LITE) set(IN3_SRC ../../../..) add_subdirectory(${IN3_SRC}/src/core build_core) -add_subdirectory(${IN3_SRC}/src/init build_init) add_subdirectory(${IN3_SRC}/src/third-party/tommath build_tommath) add_subdirectory(${IN3_SRC}/src/third-party/crypto build_crypto) @@ -37,7 +36,6 @@ add_subdirectory(${IN3_SRC}/src/api/utils build_utils) set(IN3_LIBS $ $ - $ $ $ $ diff --git a/c/test/qemu/esp32/main/in3_main.c b/c/test/qemu/esp32/main/in3_main.c index 25157c917..a25290d33 100644 --- a/c/test/qemu/esp32/main/in3_main.c +++ b/c/test/qemu/esp32/main/in3_main.c @@ -43,13 +43,14 @@ #include "sdkconfig.h" #include #include -#include // the core client -#include // functions for direct api-access -#include // if included the verifier will automaticly be initialized. -#include // logging functions -#include // the context -#include // default signer implementation -#include // stringbuilder tool for dynamic memory string handling +#include // the core client +#include // functions for direct api-access +#include // functions for nodeselection +#include // logging functions +#include // functions for direct api-access +#include // the context +#include // default signer implementation +#include // stringbuilder tool for dynamic memory string handling #include #include @@ -88,6 +89,9 @@ in3_ret_t transport_mock(void* plugin_data, in3_plugin_act_t action, void* plugi /* Setup and init in3 */ void init_in3(void) { c = in3_for_chain(CHAIN_ID_GOERLI); + in3_register_eth_full(in3); + in3_register_nodeselect_def(in3); + in3_log_set_quiet(false); in3_log_set_level(LOG_TRACE); in3_plugin_register(c, PLGN_ACT_TRANSPORT, transport_mock, NULL, true); diff --git a/c/test/qemu/zephyr-arm3/CMakeLists.txt b/c/test/qemu/zephyr-arm3/CMakeLists.txt index f1c7d46f5..1d640a4b8 100644 --- a/c/test/qemu/zephyr-arm3/CMakeLists.txt +++ b/c/test/qemu/zephyr-arm3/CMakeLists.txt @@ -26,7 +26,6 @@ ADD_DEFINITIONS(-DIN3_MATH_LITE) set(IN3_SRC ../../..) set(IN3_DEPS ${IN3_SRC}/src/core -${IN3_SRC}/src/init ${IN3_SRC}/src/verifier/eth1/basic ${IN3_SRC}/src/verifier/eth1/nano ${IN3_SRC}/src/signer/pk-signer diff --git a/c/test/qemu/zephyr-arm3/src/main.c b/c/test/qemu/zephyr-arm3/src/main.c index e0bec953b..5f3ada0be 100644 --- a/c/test/qemu/zephyr-arm3/src/main.c +++ b/c/test/qemu/zephyr-arm3/src/main.c @@ -71,9 +71,9 @@ in3_ret_t transport_mock(void* plugin_data, in3_plugin_act_t action, void* plugi in3_t* init_in3_goerli(in3_plugin_act_fn custom_transport) { in3_t* in3 = NULL; //int err; - in3_register_default(in3_register_eth_basic); - in3_register_default(in3_register_nodeselect_def); in3 = in3_for_chain(0x5); + in3_register_eth_basic(in3); + in3_register_nodeselect_def(in3); if (custom_transport) in3_plugin_register(in3, PLGN_ACT_TRANSPORT, custom_transport, NULL, true); in3->flags = FLAGS_STATS | FLAGS_INCLUDE_CODE | FLAGS_BINARY; From a1e8a6039379ab3d0ffea2addd3b8e80ec48aa7a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 13 Apr 2021 22:47:55 +0200 Subject: [PATCH 123/221] add public headers for eth verifier --- c/include/in3/eth_basic.h | 148 ++++++++++++++++++++++++ c/include/in3/{pay_eth.h => eth_full.h} | 51 ++------ c/include/in3/eth_nano.h | 82 +++++++++++++ c/src/pay/eth/pay_eth.h | 1 - c/src/verifier/eth1/basic/eth_basic.h | 2 +- c/src/verifier/eth1/full/eth_full.h | 2 +- c/src/verifier/eth1/nano/eth_nano.h | 2 +- 7 files changed, 241 insertions(+), 47 deletions(-) create mode 100644 c/include/in3/eth_basic.h rename c/include/in3/{pay_eth.h => eth_full.h} (64%) create mode 100644 c/include/in3/eth_nano.h diff --git a/c/include/in3/eth_basic.h b/c/include/in3/eth_basic.h new file mode 100644 index 000000000..1cfb76949 --- /dev/null +++ b/c/include/in3/eth_basic.h @@ -0,0 +1,148 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ +// @PUBLIC_HEADER +/** @file + * Ethereum Nanon verification. + * */ + +#ifndef in3_eth_basic_h__ +#define in3_eth_basic_h__ + +#include "plugin.h" + +/** + * Filter type used internally when managing filters. + */ +typedef enum { + FILTER_EVENT = 0, /**< Event filter */ + FILTER_BLOCK = 1, /**< Block filter */ + FILTER_PENDING = 2, /**< Pending filter (Unsupported) */ +} in3_filter_type_t; + +typedef struct in3_filter_t_ { + bool is_first_usage; /**< if true the filter was not used previously */ + in3_filter_type_t type; /**< filter type: (event, block or pending) */ + uint64_t last_block; /**< block no. when filter was created OR eth_getFilterChanges was called */ + char* options; /**< associated filter options */ + void (*release)(struct in3_filter_t_* f); /**< method to release owned resources */ +} in3_filter_t; + +/** + * Handler which is added to client config in order to handle filter. + */ +typedef struct in3_filter_handler_t_ { + in3_filter_t** array; /** array of filters */ + size_t count; /** counter for filters */ +} in3_filter_handler_t; + +/** + * returns the filters + */ +in3_filter_handler_t* eth_basic_get_filters(in3_t* c); + +/** + * verifies internal tx-values. + */ +in3_ret_t eth_verify_tx_values(in3_vctx_t* vc, d_token_t* tx, bytes_t* raw); + +/** + * verifies a transaction. + */ +in3_ret_t eth_verify_eth_getTransaction(in3_vctx_t* vc, bytes_t* tx_hash); + +/** + * verifies a transaction by block hash/number and id. + */ +in3_ret_t eth_verify_eth_getTransactionByBlock(in3_vctx_t* vc, d_token_t* blk, uint32_t tx_idx); + +/** + * verify account-proofs + */ +in3_ret_t eth_verify_account_proof(in3_vctx_t* vc); + +/** + * verifies a block + */ +in3_ret_t eth_verify_eth_getBlock(in3_vctx_t* vc, bytes_t* block_hash, uint64_t blockNumber); + +/** + * verifies block transaction count by number or hash + */ +in3_ret_t eth_verify_eth_getBlockTransactionCount(in3_vctx_t* vc, bytes_t* block_hash, uint64_t blockNumber); + +/** + * this function should only be called once and will register the eth-nano verifier. + */ +in3_ret_t in3_register_eth_basic(in3_t* c); + +/** + * verify logs + */ +in3_ret_t eth_verify_eth_getLog(in3_vctx_t* vc, int l_logs); + +/** + * prepares a transaction and writes the data to the dst-bytes. In case of success, you MUST free only the data-pointer of the dst. + */ +in3_ret_t eth_prepare_unsigned_tx(d_token_t* tx, /**< a json-token desribing the transaction */ + in3_req_t* req, /**< the current context */ + bytes_t* dst /**< the bytes to write the result to. */ +); + +/** + * signs a unsigned raw transaction and writes the raw data to the dst-bytes. In case of success, you MUST free only the data-pointer of the dst. + */ +in3_ret_t eth_sign_raw_tx(bytes_t raw_tx, /**< the unsigned raw transaction to sign */ + in3_req_t* req, /**< the current context */ + address_t from, /**< the address of the account to sign with */ + bytes_t* dst /**< the bytes to write the result to. */ +); + +/** + * expects a req-object for a transaction and converts it into a sendRawTransaction after signing. + */ +in3_ret_t handle_eth_sendTransaction(in3_req_t* req, /**< the current context */ + d_token_t* req_data /**< the request */ +); + +/** + * returns a pointer to 32 bytes marking a empty hash (keccakc(0x)) + */ +const uint8_t* empty_hash(); + +/** + * minimum signer for the wallet, returns the signed message which needs to be freed + */ +RETURNS_NONULL NONULL char* eth_wallet_sign(const char* key, const char* data); + +#endif // in3_eth_basic_h__ \ No newline at end of file diff --git a/c/include/in3/pay_eth.h b/c/include/in3/eth_full.h similarity index 64% rename from c/include/in3/pay_eth.h rename to c/include/in3/eth_full.h index e5eb3b5a8..4c075107f 100644 --- a/c/include/in3/pay_eth.h +++ b/c/include/in3/eth_full.h @@ -2,7 +2,7 @@ * This file is part of the Incubed project. * Sources: https://github.com/blockchainsllc/in3 * - * Copyright (C) 2018-2019 slock.it GmbH, Blockchains LLC + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC * * * COMMERCIAL LICENSE USAGE @@ -31,54 +31,19 @@ * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see . *******************************************************************************/ - // @PUBLIC_HEADER /** @file - * USN API. - * - * This header-file defines easy to use function, which are verifying USN-Messages. + * Ethereum Nanon verification. * */ -#ifndef PAY_ETH_H -#define PAY_ETH_H -#ifdef __cplusplus -extern "C" { -#endif -#include "client.h" -#include "plugin.h" - -typedef struct in3_pay_eth_node { - address_t address; - uint32_t price; - uint64_t payed; - struct in3_pay_eth_node* next; -} in3_pay_eth_node_t; - -typedef struct { - uint64_t bulk_size; - uint64_t max_price; - uint64_t nonce; - uint64_t gas_price; - in3_pay_eth_node_t* nodes; -} in3_pay_eth_t; +#ifndef in3_eth_full_h__ +#define in3_eth_full_h__ -/** - * Eth payment implementation - */ -in3_ret_t in3_pay_eth(void* plugin_data, in3_plugin_act_t action, void* plugin_ctx); +#include "plugin.h" /** - * get access to internal plugin data if registered + * this function should only be called once and will register the eth-full verifier. */ -static inline in3_pay_eth_t* in3_pay_eth_data(in3_t* c) { - return in3_plugin_get_data(c, in3_pay_eth); -} +in3_ret_t in3_register_eth_full(in3_t* c); -/** - * registers the Eth payment plugin - */ -in3_ret_t in3_register_pay_eth(in3_t* c); -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file +#endif // in3_eth_full_h__ \ No newline at end of file diff --git a/c/include/in3/eth_nano.h b/c/include/in3/eth_nano.h new file mode 100644 index 000000000..a777f60e4 --- /dev/null +++ b/c/include/in3/eth_nano.h @@ -0,0 +1,82 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ +// @PUBLIC_HEADER +/** @file + * Ethereum Nanon verification. + * */ + +#ifndef in3_eth_nano_h__ +#define in3_eth_nano_h__ + +#include "plugin.h" + +/** entry-function to execute the verification context. */ +NONULL in3_ret_t in3_verify_eth_nano(void* p_data, in3_plugin_act_t action, void* pctx); + +/** verifies a blockheader. */ +NONULL_FOR((1, 2)) +in3_ret_t eth_verify_blockheader(in3_vctx_t* vc, bytes_t* header, bytes_t* expected_blockhash); + +/** + * verifies a single signature blockheader. + * + * This function will return a positive integer with a bitmask holding the bit set according to the address that signed it. + * This is based on the signatiures in the request-config. + * + */ +NONULL unsigned int eth_verify_signature(in3_vctx_t* vc, bytes_t* msg_hash, d_token_t* sig); + +/** + * returns the address of the signature if the msg_hash is correct + */ +NONULL bytes_t* ecrecover_signature(bytes_t* msg_hash, d_token_t* sig); + +/** + * verifies a transaction receipt. + */ +NONULL in3_ret_t eth_verify_eth_getTransactionReceipt(in3_vctx_t* vc, bytes_t* tx_hash); + +/** + * this function should only be called once and will register the eth-nano verifier. + */ +NONULL in3_ret_t in3_register_eth_nano(in3_t* c); + +/** + * helper function to rlp-encode the transaction_index. + * + * The result must be freed after use! + */ +bytes_t* create_tx_path(uint32_t index); + +#endif // in3_eth_nano_h__ \ No newline at end of file diff --git a/c/src/pay/eth/pay_eth.h b/c/src/pay/eth/pay_eth.h index c3cab063a..68db6ec54 100644 --- a/c/src/pay/eth/pay_eth.h +++ b/c/src/pay/eth/pay_eth.h @@ -32,7 +32,6 @@ * with this program. If not, see . *******************************************************************************/ -// @PUBLIC_HEADER /** @file * USN API. * diff --git a/c/src/verifier/eth1/basic/eth_basic.h b/c/src/verifier/eth1/basic/eth_basic.h index ca556461b..1f3ba3cb9 100644 --- a/c/src/verifier/eth1/basic/eth_basic.h +++ b/c/src/verifier/eth1/basic/eth_basic.h @@ -31,7 +31,7 @@ * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see . *******************************************************************************/ - +// @PUBLIC_HEADER /** @file * Ethereum Nanon verification. * */ diff --git a/c/src/verifier/eth1/full/eth_full.h b/c/src/verifier/eth1/full/eth_full.h index 418f71e93..d768cbd29 100644 --- a/c/src/verifier/eth1/full/eth_full.h +++ b/c/src/verifier/eth1/full/eth_full.h @@ -31,7 +31,7 @@ * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see . *******************************************************************************/ - +// @PUBLIC_HEADER /** @file * Ethereum Nanon verification. * */ diff --git a/c/src/verifier/eth1/nano/eth_nano.h b/c/src/verifier/eth1/nano/eth_nano.h index ad64ffba9..cf242364e 100644 --- a/c/src/verifier/eth1/nano/eth_nano.h +++ b/c/src/verifier/eth1/nano/eth_nano.h @@ -31,7 +31,7 @@ * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see . *******************************************************************************/ - +// @PUBLIC_HEADER /** @file * Ethereum Nanon verification. * */ From 7f8be272effe7a2e6abf71ffd2bf3949582b34b1 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 14 Apr 2021 00:06:47 +0200 Subject: [PATCH 124/221] fix quemu --- c/test/qemu/esp32/main/in3_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/test/qemu/esp32/main/in3_main.c b/c/test/qemu/esp32/main/in3_main.c index a25290d33..cfb60a990 100644 --- a/c/test/qemu/esp32/main/in3_main.c +++ b/c/test/qemu/esp32/main/in3_main.c @@ -89,8 +89,8 @@ in3_ret_t transport_mock(void* plugin_data, in3_plugin_act_t action, void* plugi /* Setup and init in3 */ void init_in3(void) { c = in3_for_chain(CHAIN_ID_GOERLI); - in3_register_eth_full(in3); - in3_register_nodeselect_def(in3); + in3_register_eth_full(c); + in3_register_nodeselect_def(c); in3_log_set_quiet(false); in3_log_set_level(LOG_TRACE); From 6edd8267943b5cdfcdada0b64157939162c37981 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 14 Apr 2021 07:51:59 +0200 Subject: [PATCH 125/221] add apt-get clean --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index dd0261c47..8d9072cf3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,7 @@ COPY c /in3/c/ COPY scripts /in3/scripts/ WORKDIR /in3/ USER root -RUN apt-get update && apt-get install -y libcurl4-openssl-dev curl cmake build-essential +RUN apt-get clean && apt-get update && apt-get install -y libcurl4-openssl-dev curl cmake build-essential RUN curl https://sh.rustup.rs -sSf | bash -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" RUN cd /in3/ && mkdir build && cd build && cmake -DZKCRYPTO_LIB=true -DCMAKE_BUILD_TYPE=MinSizeRel -DIN3_SERVER=true .. && make in3 @@ -46,7 +46,7 @@ RUN cd /in3/ && mkdir build && cd build && cmake -DZKCRYPTO_LIB=true -DCMAKE_B FROM debian:buster-slim COPY --from=build /in3/build/bin/in3 /bin/in3 -RUN apt-get update && apt-get install -y curl +RUN apt-get clean && apt-get update && apt-get install -y curl EXPOSE 8545 ENTRYPOINT ["/bin/in3"] CMD ["--help"] From dcb7cb180e532f765c1878c9d9540c8fe73d8c5b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 14 Apr 2021 12:41:09 +0200 Subject: [PATCH 126/221] removed testtool --- c/src/third-party/zkcrypto/wasm/testzc.c | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 c/src/third-party/zkcrypto/wasm/testzc.c diff --git a/c/src/third-party/zkcrypto/wasm/testzc.c b/c/src/third-party/zkcrypto/wasm/testzc.c deleted file mode 100644 index 4d041f25f..000000000 --- a/c/src/third-party/zkcrypto/wasm/testzc.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#include "lib.h" -void hex(bytes_t b) { - printf("0x"); - for (int i = 0; i < b.len; i++) printf("%02x", b.data[i]); - printf("\n"); -} - -int main(int argc, char** argv) { - char* msg = "abcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklmabcdefghijklm"; - bytes32_t p; - zkcrypto_initialize(); - zkcrypto_pk_from_seed(bytes((void*) msg, 32), p); - hex(bytes(p, 32)); - - return 0; -} \ No newline at end of file From 55899425b64f6ac72daa5f586dc2bc89ea794e0a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 14 Apr 2021 12:57:43 +0200 Subject: [PATCH 127/221] removed swift from the CI --- .gitlab-ci.yml | 1 - c/src/init/in3_init.c | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c2156f71d..29a522853 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,4 +47,3 @@ include: - local: "/python/ci.yml" - local: "/dotnet/ci.yml" - local: "/rust/ci.yml" - - local: "/swift/ci.yml" diff --git a/c/src/init/in3_init.c b/c/src/init/in3_init.c index 35b8767c3..d694a5412 100644 --- a/c/src/init/in3_init.c +++ b/c/src/init/in3_init.c @@ -1,6 +1,9 @@ #include "in3_init.h" #include "../core/client/plugin.h" -#include "autoregister.h" +#ifndef IN3_AUTOINIT_PATH +#define IN3_AUTOINIT_PATH "autoregister.h" +#endif +#include IN3_AUTOINIT_PATH void zkcrypto_initialize(); From e83f067b2f561b840037c23c48ef82d3609c207a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 14 Apr 2021 15:29:17 +0200 Subject: [PATCH 128/221] remove swift --- .vscode/settings.json | 7 +- scripts/generator/swift.js | 8 +- swift/Package.swift | 32 - swift/README.md | 3 - swift/Sources/CIn3/module.modulemap | 5 - swift/Sources/In3/API/Account.swift | 433 ------- swift/Sources/In3/API/Btc.swift | 1167 ----------------- swift/Sources/In3/API/Contract.swift | 371 ------ swift/Sources/In3/API/Eth.swift | 1346 -------------------- swift/Sources/In3/API/Ipfs.swift | 70 - swift/Sources/In3/API/Nodelist.swift | 408 ------ swift/Sources/In3/API/Utils.swift | 209 --- swift/Sources/In3/API/Zksync.swift | 1011 --------------- swift/Sources/In3/Config.swift | 429 ------- swift/Sources/In3/In3.swift | 91 -- swift/Sources/In3/Utils/Cache.swift | 97 -- swift/Sources/In3/Utils/Convert.swift | 258 ---- swift/Sources/In3/Utils/Error.swift | 36 - swift/Sources/In3/Utils/JsonRpc.swift | 438 ------- swift/Sources/In3/Utils/Promise.swift | 112 -- swift/Sources/In3/Utils/Transport.swift | 222 ---- swift/Sources/In3/Utils/UInt256.swift | 229 ---- swift/Tests/In3Tests/In3Tests.swift | 107 -- swift/Tests/In3Tests/Mock.swift | 10 - swift/Tests/In3Tests/XCTestManifests.swift | 9 - swift/Tests/LinuxMain.swift | 7 - swift/ci.yml | 36 - swift/docs/1_intro.md | 33 - 28 files changed, 10 insertions(+), 7174 deletions(-) delete mode 100644 swift/Package.swift delete mode 100644 swift/README.md delete mode 100644 swift/Sources/CIn3/module.modulemap delete mode 100644 swift/Sources/In3/API/Account.swift delete mode 100644 swift/Sources/In3/API/Btc.swift delete mode 100644 swift/Sources/In3/API/Contract.swift delete mode 100644 swift/Sources/In3/API/Eth.swift delete mode 100644 swift/Sources/In3/API/Ipfs.swift delete mode 100644 swift/Sources/In3/API/Nodelist.swift delete mode 100644 swift/Sources/In3/API/Utils.swift delete mode 100644 swift/Sources/In3/API/Zksync.swift delete mode 100644 swift/Sources/In3/Config.swift delete mode 100644 swift/Sources/In3/In3.swift delete mode 100644 swift/Sources/In3/Utils/Cache.swift delete mode 100644 swift/Sources/In3/Utils/Convert.swift delete mode 100644 swift/Sources/In3/Utils/Error.swift delete mode 100644 swift/Sources/In3/Utils/JsonRpc.swift delete mode 100644 swift/Sources/In3/Utils/Promise.swift delete mode 100644 swift/Sources/In3/Utils/Transport.swift delete mode 100644 swift/Sources/In3/Utils/UInt256.swift delete mode 100644 swift/Tests/In3Tests/In3Tests.swift delete mode 100644 swift/Tests/In3Tests/Mock.swift delete mode 100644 swift/Tests/In3Tests/XCTestManifests.swift delete mode 100644 swift/Tests/LinuxMain.swift delete mode 100644 swift/ci.yml delete mode 100644 swift/docs/1_intro.md diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a4e9ce9b..575572393 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -91,7 +91,12 @@ "sha2.h": "c", "pb_decode.h": "c", "ios": "c", - "filesystem": "c" + "filesystem": "c", + "plugin.h": "c", + "request.h": "c", + "nodeselect_def.h": "c", + "in3_winhttp.h": "c", + "ed25519-hash-custom.h": "c" }, "C_Cpp.errorSquiggles": "Disabled", "C_Cpp.clang_format_fallbackStyle": "{BasedOnStyle: LLVM, AlignConsecutiveAssignments: true, AlignConsecutiveDeclarations: true, AlignTrailingComments: true, AllowShortBlocksOnASingleLine: true, AllowShortCaseLabelsOnASingleLine: true, AllowShortIfStatementsOnASingleLine: true }", diff --git a/scripts/generator/swift.js b/scripts/generator/swift.js index 1486ceb6b..892f4e3e7 100644 --- a/scripts/generator/swift.js +++ b/scripts/generator/swift.js @@ -6,7 +6,7 @@ const { camelCaseLow, camelCaseUp, } = require('./util') - +const swiftDir = '../../in3-swift' const isStruct = (c, typeConfigs) => typeof c.type == 'string' ? typeConfigs[c.type] : typeof c.type === 'object' const configs = { In3Config: [ @@ -191,7 +191,7 @@ function createSwiftInitForStruct(s, pad) { exports.generate_config = function () { Object.keys(configs).forEach(_ => createSwiftInitForStruct(configs[_], _ == 'In3Config' ? '' : ' ')) - fs.writeFileSync('../swift/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( + fs.writeFileSync(swiftDir + '/Sources/In3/Config.swift', '// This is a generated file, please don\'t edit it manually!\n\nimport Foundation\n\n' + ( configs.In3Config.join('\n') + '\n\n' + Object.keys(configs).filter(_ => _ != 'In3Config').map(type => configs[type].join('\n') + '\n }\n\n').join('') + '\n}\n' @@ -310,7 +310,7 @@ function createApiFunction(rpc_name, rpc, content, api_name, structs, types, rpc } const paramNames = Object.keys(rpc.params || {}) let x = '\n**Example**\n\n```swift\n' - let call = camelCaseUp(api_name) + '(in3).' + fnName + '(' + (ex.request || []) + let call = 'in3.' + camelCaseUp(api_name).toLowerCase() + '.' + fnName + '(' + (ex.request || []) .filter((_, i) => _ != rpc.params[paramNames[i]].internalDefault) .map((_, i) => paramNames[i] + ': ' + toSwiftValue(_, i)).join(', ') + ')' if (rpc.sync) { @@ -358,7 +358,7 @@ exports.generateAPI = function (api_name, rpcs, descr, types) { Object.keys(rpcs).forEach(rpc_name => createApiFunction(rpc_name, rpcs[rpc_name], content, api_name, structs, types, rpcs)) // write the API to the filesystem - fs.writeFileSync('../swift/Sources/In3/API/' + apiName + '.swift', ( + fs.writeFileSync(swiftDir + '/Sources/In3/API/' + apiName + '.swift', ( content.join('\n') + '\n\n}\n' + Object.values(structs).join('\n\n') ), 'utf8') diff --git a/swift/Package.swift b/swift/Package.swift deleted file mode 100644 index 747144443..000000000 --- a/swift/Package.swift +++ /dev/null @@ -1,32 +0,0 @@ -// swift-tools-version:5.3 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "In3", - platforms: [ - .macOS(.v10_15), - ], - products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. - .library( - name: "In3", - targets: ["In3"]), - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. - .systemLibrary( - name: "CIn3"), - .target( - name: "In3", - dependencies: ["CIn3"], - linkerSettings: [ - .unsafeFlags(["-L../build/lib"]) - ]), - .testTarget( - name: "In3Tests", - dependencies: ["In3"]), - ] -) diff --git a/swift/README.md b/swift/README.md deleted file mode 100644 index 370ade086..000000000 --- a/swift/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# In3 - -A description of this package. diff --git a/swift/Sources/CIn3/module.modulemap b/swift/Sources/CIn3/module.modulemap deleted file mode 100644 index 827c5a4cb..000000000 --- a/swift/Sources/CIn3/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -module CIn3 [system] { - umbrella header "../../../c/include/in3.rs.h" - link "in3" - export * -} diff --git a/swift/Sources/In3/API/Account.swift b/swift/Sources/In3/API/Account.swift deleted file mode 100644 index 333e59ba3..000000000 --- a/swift/Sources/In3/API/Account.swift +++ /dev/null @@ -1,433 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// Account Handling includes handling signers and preparing and signing transacrtion and data. -/// -/// Signers are Plugins able to create signatures. Those functions will use the registered plugins. -/// -public class Account { - internal var in3: In3 - - /// initialiazes the Account API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// extracts the address from a private key. - /// - Parameter pk : the 32 bytes private key as hex. - /// - Returns: the address - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).pk2address(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") - /// // result = "0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd" - /// ``` - /// - public func pk2address(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2address", params:RPCObject( pk), convertWith: toString ) - } - - /// extracts the public key from a private key. - /// - Parameter pk : the 32 bytes private key as hex. - /// - Returns: the public key as 64 bytes - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).pk2public(pk: "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a") - /// // result = "0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f7818\ - /// // 6577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1" - /// ``` - /// - public func pk2public(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_pk2public", params:RPCObject( pk), convertWith: toString ) - } - - /// extracts the public key and address from signature. - /// - Parameter msg : the message the signature is based on. - /// - Parameter sig : the 65 bytes signature as hex. - /// - Parameter sigtype : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data). Default: `raw` - /// - Returns: the extracted public key and address - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).ecrecover(msg: "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999", sig: "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c", sigtype: "hash") - /// // result = - /// // publicKey: "0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c\ - /// // 4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb" - /// // address: "0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4" - /// ``` - /// - public func ecrecover(msg: String, sig: String, sigtype: String? = "raw") throws -> AccountEcrecover { - return try execLocalAndConvert(in3: in3, method: "in3_ecrecover", params:RPCObject( msg), RPCObject( sig), sigtype == nil ? RPCObject.none : RPCObject( sigtype! ), convertWith: { try AccountEcrecover($0,$1) } ) - } - - /// prepares a Transaction by filling the unspecified values and returens the unsigned raw Transaction. - /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Returns: the unsigned raw transaction as hex. - /// - /// **Example** - /// - /// ```swift - /// Account(in3).prepareTx(tx: AccountTransaction(to: "0x63f666a23cbd135a91187499b5cc51d589c302a0", value: "0x100000000", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f")) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a0850100000000\ - /// // 80018080" - /// } - /// } - /// - /// ``` - /// - public func prepareTx(tx: AccountTransaction) -> Future { - return execAndConvert(in3: in3, method: "in3_prepareTx", params:RPCObject( tx.toRPCDict()), convertWith: toString ) - } - - /// signs the given raw Tx (as prepared by in3_prepareTx ). The resulting data can be used in `eth_sendRawTransaction` to publish and broadcast the transaction. - /// - Parameter tx : the raw unsigned transactiondata - /// - Parameter from : the account to sign - /// - Returns: the raw transaction with signature. - /// - /// **Example** - /// - /// ```swift - /// Account(in3).signTx(tx: "0xe980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a085010000000080018080", from: "0xc2b2f4ad0d234b8c135c39eea8409b448e5e496f") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xf86980851a13b865b38252089463f666a23cbd135a91187499b5cc51d589c302a08501000000\ - /// // 008026a03c5b094078383f3da3f65773ab1314e89ee76bc41f827f2ef211b2d3449e4435a077755\ - /// // f8d9b32966e1ad8f6c0e8c9376a4387ed237bdbf2db6e6b94016407e276" - /// } - /// } - /// - /// ``` - /// - public func signTx(tx: String, from: String) -> Future { - return execAndConvert(in3: in3, method: "in3_signTx", params:RPCObject( tx), RPCObject( from), convertWith: toString ) - } - - /// signs the given data. - /// - Parameter msg : the message to sign. - /// - Parameter account : the account to sign if the account is a bytes32 it will be used as private key - /// - Parameter msgType : the type of the signature data : `eth_sign` (use the prefix and hash it), `raw` (hash the raw data), `hash` (use the already hashed data) - /// - Returns: the signature - /// - /// **Example** - /// - /// ```swift - /// Account(in3).signData(msg: "0x0102030405060708090a0b0c0d0e0f", account: "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852", msgType: "raw") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // message: "0x0102030405060708090a0b0c0d0e0f" - /// // messageHash: "0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67" - /// // signature: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792\ - /// // 264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b" - /// // r: "0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579" - /// // s: "0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152" - /// // v: 27 - /// } - /// } - /// - /// ``` - /// - public func signData(msg: String, account: String, msgType: String? = "raw") -> Future { - return execAndConvert(in3: in3, method: "in3_signData", params:RPCObject( msg), RPCObject( account), msgType == nil ? RPCObject.none : RPCObject( msgType! ), convertWith: { try AccountSignData($0,$1) } ) - } - - /// decrypts a JSON Keystore file as defined in the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). The result is the raw private key. - /// - Parameter key : Keydata as object as defined in the keystorefile - /// - Parameter passphrase : the password to decrypt it. - /// - Returns: a raw private key (32 bytes) - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).decryptKey(key: {"version":"3,","id":"f6b5c0b1-ba7a-4b67-9086-a01ea54ec638","address":"08aa30739030f362a8dd597fd3fcde283e36f4a1","crypto":{"ciphertext":"d5c5aafdee81d25bb5ac4048c8c6954dd50c595ee918f120f5a2066951ef992d","cipherparams":{"iv":"415440d2b1d6811d5c8a3f4c92c73f49"},"cipher":"aes-128-ctr","kdf":"pbkdf2","kdfparams":{"dklen":32,"salt":"691e9ad0da2b44404f65e0a60cf6aabe3e92d2c23b7410fd187eeeb2c1de4a0d","c":16384,"prf":"hmac-sha256"},"mac":"de651c04fc67fd552002b4235fa23ab2178d3a500caa7070b554168e73359610"}}, passphrase: "test") - /// // result = "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" - /// ``` - /// - public func decryptKey(key: String, passphrase: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_decryptKey", params:RPCObject( key), RPCObject( passphrase), convertWith: toString ) - } - - /// Generates 32 random bytes. - /// If /dev/urandom is available it will be used and should generate a secure random number. - /// If not the number should not be considered sceure or used in production. - /// - /// - Parameter seed : the seed. If given the result will be deterministic. - /// - Returns: the 32byte random data - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).createKey() - /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - /// ``` - /// - public func createKey(seed: String? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_createKey", params:seed == nil ? RPCObject.none : RPCObject( seed! ), convertWith: toString ) - } - - /// The sign method calculates an Ethereum specific signature with: - /// - /// ```js - /// sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). - /// ``` - /// - /// By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim. - /// - /// For the address to sign a signer must be registered. - /// - /// - Parameter account : the account to sign with - /// - Parameter message : the message to sign - /// - Returns: the signature (65 bytes) for the given message. - /// - /// **Example** - /// - /// ```swift - /// Account(in3).sign(account: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", message: "0xdeadbeaf") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ - /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" - /// } - /// } - /// - /// ``` - /// - public func sign(account: String, message: String) -> Future { - return execAndConvert(in3: in3, method: "eth_sign", params:RPCObject( account), RPCObject( message), convertWith: toString ) - } - - /// Signs a transaction that can be submitted to the network at a later time using with eth_sendRawTransaction. - /// - Parameter tx : transaction to sign - /// - Returns: the raw signed transaction - /// - /// **Example** - /// - /// ```swift - /// Account(in3).signTransaction(tx: AccountTransaction(data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155", gas: "0x76c0", gasPrice: "0x9184e72a000", to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567", value: "0x9184e72a")) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17b\ - /// // fdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b" - /// } - /// } - /// - /// ``` - /// - public func signTransaction(tx: AccountTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_signTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) - } - - /// adds a raw private key as signer, which allows signing transactions. - /// - Parameter pk : the 32byte long private key as hex string. - /// - Returns: the address of given key. - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).addRawKey(pk: "0x1234567890123456789012345678901234567890123456789012345678901234") - /// // result = "0x2e988a386a799f506693793c6a5af6b54dfaabfb" - /// ``` - /// - public func addRawKey(pk: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_addRawKey", params:RPCObject( pk), convertWith: toString ) - } - - /// returns a array of account-addresss the incubed client is able to sign with. - /// - /// In order to add keys, you can use [in3_addRawKey](#in3-addrawkey) or configure them in the config. The result also contains the addresses of any signer signer-supporting the `PLGN_ACT_SIGN_ACCOUNT` action. - /// - /// - Returns: the array of addresses of all registered signers. - /// - /// **Example** - /// - /// ```swift - /// let result = try Account(in3).accounts() - /// // result = - /// // - "0x2e988a386a799f506693793c6a5af6b54dfaabfb" - /// // - "0x93793c6a5af6b54dfaabfb2e988a386a799f5066" - /// ``` - /// - public func accounts() throws -> [String] { - return try execLocalAndConvert(in3: in3, method: "eth_accounts", convertWith: { try toArray($0,$1)!.map({ try toString($0, false)! }) } ) - } - - -} -/// the extracted public key and address -public struct AccountEcrecover { - /// the public Key of the signer (64 bytes) - public var publicKey: String - - /// the address - public var address: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - publicKey = try toString(obj["publicKey"],false)! - address = try toString(obj["address"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["publicKey"] = RPCObject( publicKey ) - obj["address"] = RPCObject( address ) - return obj - } - - /// initialize the AccountEcrecover - /// - /// - Parameter publicKey : the public Key of the signer (64 bytes) - /// - Parameter address : the address - public init(publicKey: String, address: String) { - self.publicKey = publicKey - self.address = address - } -} - -/// the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). -public struct AccountTransaction { - /// receipient of the transaction. - public var to: String? - - /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String? - - /// value in wei to send - public var value: UInt256? - - /// the gas to be send along - public var gas: UInt64? - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64? - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64? - - /// the data-section of the transaction - public var data: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],true)! - from = try toString(obj["from"],true)! - value = try toUInt256(obj["value"],true)! - gas = try toUInt64(obj["gas"],true)! - gasPrice = try toUInt64(obj["gasPrice"],true)! - nonce = try toUInt64(obj["nonce"],true)! - data = try toString(obj["data"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - if let x = to { obj["to"] = RPCObject( x ) } - if let x = from { obj["from"] = RPCObject( x ) } - if let x = value { obj["value"] = RPCObject( x.hexValue ) } - if let x = gas { obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = gasPrice { obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = nonce { obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = data { obj["data"] = RPCObject( x ) } - return obj - } - - /// initialize the AccountTransaction - /// - /// - Parameter to : receipient of the transaction. - /// - Parameter from : sender of the address (if not sepcified, the first signer will be the sender) - /// - Parameter value : value in wei to send - /// - Parameter gas : the gas to be send along - /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - /// - Parameter data : the data-section of the transaction - public init(to: String? = nil, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { - self.to = to - self.from = from - self.value = value - self.gas = gas - self.gasPrice = gasPrice - self.nonce = nonce - self.data = data - } -} - -/// the signature -public struct AccountSignData { - /// original message used - public var message: String - - /// the hash the signature is based on - public var messageHash: String - - /// the signature (65 bytes) - public var signature: String - - /// the x-value of the EC-Point - public var r: String - - /// the y-value of the EC-Point - public var s: String - - /// the recovery value (0|1) + 27 - public var v: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - message = try toString(obj["message"],false)! - messageHash = try toString(obj["messageHash"],false)! - signature = try toString(obj["signature"],false)! - r = try toString(obj["r"],false)! - s = try toString(obj["s"],false)! - v = try toString(obj["v"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["message"] = RPCObject( message ) - obj["messageHash"] = RPCObject( messageHash ) - obj["signature"] = RPCObject( signature ) - obj["r"] = RPCObject( r ) - obj["s"] = RPCObject( s ) - obj["v"] = RPCObject( v ) - return obj - } - - /// initialize the AccountSignData - /// - /// - Parameter message : original message used - /// - Parameter messageHash : the hash the signature is based on - /// - Parameter signature : the signature (65 bytes) - /// - Parameter r : the x-value of the EC-Point - /// - Parameter s : the y-value of the EC-Point - /// - Parameter v : the recovery value (0|1) + 27 - public init(message: String, messageHash: String, signature: String, r: String, s: String, v: String) { - self.message = message - self.messageHash = messageHash - self.signature = signature - self.r = r - self.s = s - self.v = v - } -} \ No newline at end of file diff --git a/swift/Sources/In3/API/Btc.swift b/swift/Sources/In3/API/Btc.swift deleted file mode 100644 index ce4d1793f..000000000 --- a/swift/Sources/In3/API/Btc.swift +++ /dev/null @@ -1,1167 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* -/// -/// For bitcoin incubed follows the specification as defined in [https://bitcoincore.org/en/doc/0.18.0/](https://bitcoincore.org/en/doc/0.18.0/). -/// Internally the in3-server will add proofs as part of the responses. The proof data differs between the methods. You will read which proof data will be provided and how the data can be used to prove the result for each method. -/// -/// Proofs will add a special `in3`-section to the response containing a `proof`- object. This object will contain parts or all of the following properties: -/// -/// * **block** -/// * **final** -/// * **txIndex** -/// * **merkleProof** -/// * **cbtx** -/// * **cbtxMerkleProof** -/// -public class Btc { - internal var in3: In3 - - /// initialiazes the Btc API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// returns a hex representation of the blockheader - /// - Parameter hash : The block hash - /// - Returns: the blockheader. - /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - /// - verbose `1` or `true`: an object representing the blockheader. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getblockheaderAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d - /// } - /// } - /// - /// ``` - /// - public func getblockheaderAsHex(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblockheader", params:RPCObject( hash), RPCObject(0), convertWith: toString ) - } - - /// returns the blockheader - /// - Parameter hash : The block hash - /// - Returns: the blockheader. - /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - /// - verbose `1` or `true`: an object representing the blockheader. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getblockheader(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 - /// // confirmations: 8268 - /// // height: 624958 - /// // version: 536928256 - /// // versionHex: 2000 - /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb - /// // time: 1586333924 - /// // mediantime: 1586332639 - /// // nonce: 1985217615 - /// // bits: 17143b41 - /// // difficulty: 13912524048945.91 - /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 - /// // nTx: 33 - /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 - /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 - /// } - /// } - /// - /// ``` - /// - public func getblockheader(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblockheader", params:RPCObject( hash), RPCObject(1), convertWith: { try Btcblockheader($0,$1) } ) - } - - /// returns a hex representation of the block - /// - Parameter hash : The block hash - /// - Returns: the block. - /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - /// - verbose `1` or `true`: an object representing the blockheader. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getBlockAsHex(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d - /// } - /// } - /// - /// ``` - /// - public func getBlockAsHex(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(0), convertWith: toString ) - } - - /// returns the block with transactionhashes - /// - Parameter hash : The block hash - /// - Returns: the block. - /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - /// - verbose `1` or `true`: an object representing the blockheader. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getBlock(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 - /// // confirmations: 8268 - /// // height: 624958 - /// // version: 536928256 - /// // versionHex: 2000 - /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb - /// // time: 1586333924 - /// // mediantime: 1586332639 - /// // nonce: 1985217615 - /// // bits: 17143b41 - /// // difficulty: 13912524048945.91 - /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 - /// // tx: - /// // - d79ffc80e07fe9e0083319600c59d47afe69995b1357be6e5dba035675780290 - /// // - ... - /// // - 6456819bfa019ba30788620153ea9a361083cb888b3662e2ff39c0f7adf16919 - /// // nTx: 33 - /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 - /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 - /// } - /// } - /// - /// ``` - /// - public func getBlock(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(1), convertWith: { try Btcblock($0,$1) } ) - } - - /// returns the block with full transactions - /// - Parameter hash : The block hash - /// - Returns: the block. - /// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader - /// - verbose `1` or `true`: an object representing the blockheader. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getBlockWithTx(hash: "000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // hash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 - /// // confirmations: 8268 - /// // height: 624958 - /// // version: 536928256 - /// // versionHex: 2000 - /// // merkleroot: d786a334ea8c65f39272d5b9be505ac3170f3904842bd52525538a9377b359cb - /// // time: 1586333924 - /// // mediantime: 1586332639 - /// // nonce: 1985217615 - /// // bits: 17143b41 - /// // difficulty: 13912524048945.91 - /// // chainwork: 00000000000000000000000000000000000000000e4c88b66c5ee78deff0d494 - /// // tx: - /// // - d79ffc80e07fe9e0083319600c59d47afe69995b1357be6e5dba035675780290 - /// // - ... - /// // - 6456819bfa019ba30788620153ea9a361083cb888b3662e2ff39c0f7adf16919 - /// // nTx: 33 - /// // previousblockhash: 00000000000000000013cba040837778744ce66961cfcf2e7c34bb3d194c7f49 - /// // nextblockhash: 0000000000000000000c799dc0e36302db7fbb471711f140dc308508ef19e343 - /// } - /// } - /// - /// ``` - /// - public func getBlockWithTx(hash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "getblock", params:RPCObject( hash), RPCObject(2), convertWith: { try BtcblockWithTx($0,$1) } ) - } - - /// returns a hex representation of the tx - /// - Parameter txid : The transaction id - /// - Parameter blockhash : The block in which to look for the transaction - /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` - /// - verbose `1` or `false`: an object representing the transaction. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getRawTransactionAsHex(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d - /// } - /// } - /// - /// ``` - /// - public func getRawTransactionAsHex(txid: String, blockhash: String? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "getrawtransaction", params:RPCObject( txid), RPCObject(0), blockhash == nil ? RPCObject.none : RPCObject( blockhash! ), convertWith: toString ) - } - - /// returns the raw transaction - /// - Parameter txid : The transaction id - /// - Parameter blockhash : The block in which to look for the transaction - /// - Returns: - verbose `0` or `false`: a string that is serialized, hex-encoded data for `txid` - /// - verbose `1` or `false`: an object representing the transaction. - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getRawTransaction(txid: "f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf", verbosity: true) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // in_active_chain: true - /// // txid: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf - /// // hash: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf - /// // version: 1 - /// // size: 518 - /// // vsize: 518 - /// // weight: 2072 - /// // locktime: 0 - /// // vin: - /// // - txid: 0a74f6e5f99bc69af80da9f0d9878ea6afbfb5fbb2d43f1ff899bcdd641a098c - /// // vout: 0 - /// // scriptSig: - /// // asm: 30440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228cc...254874 - /// // hex: 4730440220481f2b3a49b202e26c73ac1b7bce022e4a74aff08473228...254874 - /// // sequence: 4294967295 - /// // - txid: 869c5e82d4dfc3139c8a153d2ee126e30a467cf791718e6ea64120e5b19e5044 - /// // vout: 0 - /// // scriptSig: - /// // asm: 3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d - /// // hex: 483045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745...f3255d - /// // sequence: 4294967295 - /// // - txid: 8a03d29a1b8ae408c94a2ae15bef8329bc3d6b04c063d36b2e8c997273fa8eff - /// // vout: 1 - /// // scriptSig: - /// // asm: 304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d1284...0045da - /// // hex: 47304402200bf7c5c7caec478bf6d7e9c5127c71505034302056d12...0045da - /// // sequence: 4294967295 - /// // vout: - /// // - value: 0.00017571 - /// // n: 0 - /// // scriptPubKey: - /// // asm: OP_DUP OP_HASH160 53196749b85367db9443ef9a5aec25cf0bdceedf OP_EQUALVERIFY - /// // OP_CHECKSIG - /// // hex: 76a91453196749b85367db9443ef9a5aec25cf0bdceedf88ac - /// // reqSigs: 1 - /// // type: pubkeyhash - /// // addresses: - /// // - 18aPWzBTq1nzs9o86oC9m3BQbxZWmV82UU - /// // - value: 0.00915732 - /// // n: 1 - /// // scriptPubKey: - /// // asm: OP_HASH160 8bb2b4b848d0b6336cc64ea57ae989630f447cba OP_EQUAL - /// // hex: a9148bb2b4b848d0b6336cc64ea57ae989630f447cba87 - /// // reqSigs: 1 - /// // type: scripthash - /// // addresses: - /// // - 3ERfvuzAYPPpACivh1JnwYbBdrAjupTzbw - /// // hex: 01000000038c091a64ddbc99f81f3fd4b2fbb5bfafa68e8...000000 - /// // blockhash: 000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220 - /// // confirmations: 15307 - /// // time: 1586333924 - /// // blocktime: 1586333924 - /// } - /// } - /// - /// ``` - /// - public func getRawTransaction(txid: String, blockhash: String? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "getrawtransaction", params:RPCObject( txid), RPCObject(1), blockhash == nil ? RPCObject.none : RPCObject( blockhash! ), convertWith: { try Btctransaction($0,$1) } ) - } - - /// Returns the number of blocks in the longest blockchain. - /// - Returns: the current blockheight - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getblockcount() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 640387 - /// } - /// } - /// - /// ``` - /// - public func getblockcount() -> Future { - return execAndConvert(in3: in3, method: "getblockcount", convertWith: toUInt64 ) - } - - /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. - /// - Parameter blocknumber : Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`) - /// - Returns: - `blocknumber` is a certain number: the difficulty of this block - /// - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) - /// - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getdifficulty(blocknumber: 631910) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 15138043247082.88 - /// } - /// } - /// - /// ``` - /// - public func getdifficulty(blocknumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "getdifficulty", params:RPCObject( String(format: "0x%1x", blocknumber)), convertWith: toUInt256 ) - } - - /// Whenever the client is not able to trust the changes of the target (which is the case if a block can't be found in the verified target cache *and* the value of the target changed more than the client's limit `max_diff`) he will call this method. It will return additional proof data to verify the changes of the target on the side of the client. This is not a standard Bitcoin rpc-method like the other ones, but more like an internal method. - /// - Parameter target_dap : the number of the difficulty adjustment period (dap) we are looking for - /// - Parameter verified_dap : the number of the closest already verified dap - /// - Parameter max_diff : the maximum target difference between 2 verified daps - /// - Parameter max_dap : the maximum amount of daps between 2 verified daps - /// - Parameter limit : the maximum amount of daps to return (`0` = no limit) - this is important for embedded devices since returning all daps might be too much for limited memory - /// - Returns: A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).proofTarget(target_dap: 230, verified_dap: 200, max_diff: 5, max_dap: 5, limit: 15) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // - dap: 205 - /// // block: 0x04000000e62ef28cb9793f4f9cd2a67a58c1e7b593129b9b...0ab284 - /// // final: 0x04000000cc69b68b702321adf4b0c485fdb1f3d6c1ddd140...090a5b - /// // cbtx: 0x01000000...1485ce370573be63d7cc1b9efbad3489eb57c8...000000 - /// // cbtxMerkleProof: 0xc72dffc1cb4cbeab960d0d2bdb80012acf7f9c...affcf4 - /// // - dap: 210 - /// // block: 0x0000003021622c26a4e62cafa8e434c7e083f540bccc8392...b374ce - /// // final: 0x00000020858f8e5124cd516f4d5e6a078f7083c12c48e8cd...308c3d - /// // cbtx: 0x01000000...c075061b4b6e434d696e657242332d50314861...000000 - /// // cbtxMerkleProof: 0xf2885d0bac15fca7e1644c1162899ecd43d52b...93761d - /// // - dap: 215 - /// // block: 0x000000202509b3b8e4f98290c7c9551d180eb2a463f0b978...f97b64 - /// // final: 0x0000002014c7c0ed7c33c59259b7b508bebfe3974e1c99a5...eb554e - /// // cbtx: 0x01000000...90133cf94b1b1c40fae077a7833c0fe0ccc474...000000 - /// // cbtxMerkleProof: 0x628c8d961adb157f800be7cfb03ffa1b53d3ad...ca5a61 - /// // - dap: 220 - /// // block: 0x00000020ff45c783d09706e359dcc76083e15e51839e4ed5...ddfe0e - /// // final: 0x0000002039d2f8a1230dd0bee50034e8c63951ab812c0b89...5670c5 - /// // cbtx: 0x01000000...b98e79fb3e4b88aefbc8ce59e82e99293e5b08...000000 - /// // cbtxMerkleProof: 0x16adb7aeec2cf254db0bab0f4a5083fb0e0a3f...63a4f4 - /// // - dap: 225 - /// // block: 0x02000020170fad0b6b1ccbdc4401d7b1c8ee868c6977d6ce...1e7f8f - /// // final: 0x0400000092945abbd7b9f0d407fcccbf418e4fc20570040c...a9b240 - /// // cbtx: 0x01000000...cf6e8f930acb8f38b588d76cd8c3da3258d5a7...000000 - /// // cbtxMerkleProof: 0x25575bcaf3e11970ccf835e88d6f97bedd6b85...bfdf46 - /// } - /// } - /// - /// ``` - /// - public func proofTarget(target_dap: UInt64, verified_dap: UInt64, max_diff: Int? = 5, max_dap: Int? = 5, limit: Int? = 0) -> Future<[BtcProofTarget]> { - return execAndConvert(in3: in3, method: "btc_proofTarget", params:RPCObject( String(format: "0x%1x", target_dap)), RPCObject( String(format: "0x%1x", verified_dap)), max_diff == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", max_diff!) ), max_dap == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", max_dap!) ), limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), convertWith: { try toArray($0,$1)!.map({ try BtcProofTarget($0,false)! }) } ) - } - - /// Returns the hash of the best (tip) block in the longest blockchain. - /// - Returns: the hash of the best block - /// - /// **Example** - /// - /// ```swift - /// Btc(in3).getbestblockhash() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 000000000000000000039cbb4e842de0de9651852122b117d7ae6d7ac4fc1df6 - /// } - /// } - /// - /// ``` - /// - public func getbestblockhash() -> Future { - return execAndConvert(in3: in3, method: "getbestblockhash", convertWith: toString ) - } - - -} -/// the blockheader. -/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader -/// - verbose `1` or `true`: an object representing the blockheader. -/// -public struct Btcblockheader { - /// the block hash (same as provided) - public var hash: String - - /// The number of confirmations, or -1 if the block is not on the main chain - public var confirmations: Int - - /// The block height or index - public var height: UInt64 - - /// The block version - public var version: Int - - /// The block version formatted in hexadecimal - public var versionHex: String - - /// The merkle root ( 32 bytes ) - public var merkleroot: String - - /// The block time in seconds since epoch (Jan 1 1970 GMT) - public var time: UInt64 - - /// The median block time in seconds since epoch (Jan 1 1970 GMT) - public var mediantime: UInt64 - - /// The nonce - public var nonce: UInt64 - - /// The bits ( 4 bytes as hex) representing the target - public var bits: String - - /// The difficulty - public var difficulty: UInt256 - - /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: String - - /// The number of transactions in the block. - public var nTx: Int - - /// The hash of the previous block - public var previousblockhash: String - - /// The hash of the next block - public var nextblockhash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - hash = try toString(obj["hash"],false)! - confirmations = try toInt(obj["confirmations"],false)! - height = try toUInt64(obj["height"],false)! - version = try toInt(obj["version"],false)! - versionHex = try toString(obj["versionHex"],false)! - merkleroot = try toString(obj["merkleroot"],false)! - time = try toUInt64(obj["time"],false)! - mediantime = try toUInt64(obj["mediantime"],false)! - nonce = try toUInt64(obj["nonce"],false)! - bits = try toString(obj["bits"],false)! - difficulty = try toUInt256(obj["difficulty"],false)! - chainwork = try toString(obj["chainwork"],false)! - nTx = try toInt(obj["nTx"],false)! - previousblockhash = try toString(obj["previousblockhash"],false)! - nextblockhash = try toString(obj["nextblockhash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject( hash ) - obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) - obj["height"] = RPCObject( String(format: "0x%1x", arguments: [height]) ) - obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) - obj["versionHex"] = RPCObject( versionHex ) - obj["merkleroot"] = RPCObject( merkleroot ) - obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) - obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["bits"] = RPCObject( bits ) - obj["difficulty"] = RPCObject( difficulty.hexValue ) - obj["chainwork"] = RPCObject( chainwork ) - obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) - obj["previousblockhash"] = RPCObject( previousblockhash ) - obj["nextblockhash"] = RPCObject( nextblockhash ) - return obj - } - - /// initialize the Btcblockheader - /// - /// - Parameter hash : the block hash (same as provided) - /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain - /// - Parameter height : The block height or index - /// - Parameter version : The block version - /// - Parameter versionHex : The block version formatted in hexadecimal - /// - Parameter merkleroot : The merkle root ( 32 bytes ) - /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter nonce : The nonce - /// - Parameter bits : The bits ( 4 bytes as hex) representing the target - /// - Parameter difficulty : The difficulty - /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) - /// - Parameter nTx : The number of transactions in the block. - /// - Parameter previousblockhash : The hash of the previous block - /// - Parameter nextblockhash : The hash of the next block - public init(hash: String, confirmations: Int, height: UInt64, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, previousblockhash: String, nextblockhash: String) { - self.hash = hash - self.confirmations = confirmations - self.height = height - self.version = version - self.versionHex = versionHex - self.merkleroot = merkleroot - self.time = time - self.mediantime = mediantime - self.nonce = nonce - self.bits = bits - self.difficulty = difficulty - self.chainwork = chainwork - self.nTx = nTx - self.previousblockhash = previousblockhash - self.nextblockhash = nextblockhash - } -} - -/// the block. -/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader -/// - verbose `1` or `true`: an object representing the blockheader. -/// -public struct Btcblock { - /// the block hash (same as provided) - public var hash: String - - /// The number of confirmations, or -1 if the block is not on the main chain - public var confirmations: Int - - /// The block height or index - public var height: UInt256 - - /// The block version - public var version: Int - - /// The block version formatted in hexadecimal - public var versionHex: String - - /// The merkle root ( 32 bytes ) - public var merkleroot: String - - /// The block time in seconds since epoch (Jan 1 1970 GMT) - public var time: UInt64 - - /// The median block time in seconds since epoch (Jan 1 1970 GMT) - public var mediantime: UInt64 - - /// The nonce - public var nonce: UInt64 - - /// The bits ( 4 bytes as hex) representing the target - public var bits: String - - /// The difficulty - public var difficulty: UInt256 - - /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: String - - /// The number of transactions in the block. - public var nTx: Int - - /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) - public var tx: [String] - - /// The hash of the previous block - public var previousblockhash: String - - /// The hash of the next block - public var nextblockhash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - hash = try toString(obj["hash"],false)! - confirmations = try toInt(obj["confirmations"],false)! - height = try toUInt256(obj["height"],false)! - version = try toInt(obj["version"],false)! - versionHex = try toString(obj["versionHex"],false)! - merkleroot = try toString(obj["merkleroot"],false)! - time = try toUInt64(obj["time"],false)! - mediantime = try toUInt64(obj["mediantime"],false)! - nonce = try toUInt64(obj["nonce"],false)! - bits = try toString(obj["bits"],false)! - difficulty = try toUInt256(obj["difficulty"],false)! - chainwork = try toString(obj["chainwork"],false)! - nTx = try toInt(obj["nTx"],false)! - tx = try toArray(obj["tx"])!.map({ try toString($0,false)! }) - previousblockhash = try toString(obj["previousblockhash"],false)! - nextblockhash = try toString(obj["nextblockhash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject( hash ) - obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) - obj["height"] = RPCObject( height.hexValue ) - obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) - obj["versionHex"] = RPCObject( versionHex ) - obj["merkleroot"] = RPCObject( merkleroot ) - obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) - obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["bits"] = RPCObject( bits ) - obj["difficulty"] = RPCObject( difficulty.hexValue ) - obj["chainwork"] = RPCObject( chainwork ) - obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) - obj["tx"] = RPCObject( tx ) - obj["previousblockhash"] = RPCObject( previousblockhash ) - obj["nextblockhash"] = RPCObject( nextblockhash ) - return obj - } - - /// initialize the Btcblock - /// - /// - Parameter hash : the block hash (same as provided) - /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain - /// - Parameter height : The block height or index - /// - Parameter version : The block version - /// - Parameter versionHex : The block version formatted in hexadecimal - /// - Parameter merkleroot : The merkle root ( 32 bytes ) - /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter nonce : The nonce - /// - Parameter bits : The bits ( 4 bytes as hex) representing the target - /// - Parameter difficulty : The difficulty - /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) - /// - Parameter nTx : The number of transactions in the block. - /// - Parameter tx : the array of transactions either as ids (verbose=1) or full transaction (verbose=2) - /// - Parameter previousblockhash : The hash of the previous block - /// - Parameter nextblockhash : The hash of the next block - public init(hash: String, confirmations: Int, height: UInt256, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, tx: [String], previousblockhash: String, nextblockhash: String) { - self.hash = hash - self.confirmations = confirmations - self.height = height - self.version = version - self.versionHex = versionHex - self.merkleroot = merkleroot - self.time = time - self.mediantime = mediantime - self.nonce = nonce - self.bits = bits - self.difficulty = difficulty - self.chainwork = chainwork - self.nTx = nTx - self.tx = tx - self.previousblockhash = previousblockhash - self.nextblockhash = nextblockhash - } -} - -/// the block. -/// - verbose `0` or `false`: a hex string with 80 bytes representing the blockheader -/// - verbose `1` or `true`: an object representing the blockheader. -/// -public struct BtcblockWithTx { - /// the block hash (same as provided) - public var hash: String - - /// The number of confirmations, or -1 if the block is not on the main chain - public var confirmations: Int - - /// The block height or index - public var height: UInt64 - - /// The block version - public var version: Int - - /// The block version formatted in hexadecimal - public var versionHex: String - - /// The merkle root ( 32 bytes ) - public var merkleroot: String - - /// The block time in seconds since epoch (Jan 1 1970 GMT) - public var time: UInt64 - - /// The median block time in seconds since epoch (Jan 1 1970 GMT) - public var mediantime: UInt64 - - /// The nonce - public var nonce: UInt64 - - /// The bits ( 4 bytes as hex) representing the target - public var bits: String - - /// The difficulty - public var difficulty: UInt256 - - /// Expected number of hashes required to produce the current chain (in hex) - public var chainwork: String - - /// The number of transactions in the block. - public var nTx: Int - - /// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) - public var tx: [Btctransaction] - - /// The hash of the previous block - public var previousblockhash: String - - /// The hash of the next block - public var nextblockhash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - hash = try toString(obj["hash"],false)! - confirmations = try toInt(obj["confirmations"],false)! - height = try toUInt64(obj["height"],false)! - version = try toInt(obj["version"],false)! - versionHex = try toString(obj["versionHex"],false)! - merkleroot = try toString(obj["merkleroot"],false)! - time = try toUInt64(obj["time"],false)! - mediantime = try toUInt64(obj["mediantime"],false)! - nonce = try toUInt64(obj["nonce"],false)! - bits = try toString(obj["bits"],false)! - difficulty = try toUInt256(obj["difficulty"],false)! - chainwork = try toString(obj["chainwork"],false)! - nTx = try toInt(obj["nTx"],false)! - tx = try toArray(obj["tx"])!.map({ try Btctransaction($0,false)! }) - previousblockhash = try toString(obj["previousblockhash"],false)! - nextblockhash = try toString(obj["nextblockhash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["hash"] = RPCObject( hash ) - obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) - obj["height"] = RPCObject( String(format: "0x%1x", arguments: [height]) ) - obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) - obj["versionHex"] = RPCObject( versionHex ) - obj["merkleroot"] = RPCObject( merkleroot ) - obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) - obj["mediantime"] = RPCObject( String(format: "0x%1x", arguments: [mediantime]) ) - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["bits"] = RPCObject( bits ) - obj["difficulty"] = RPCObject( difficulty.hexValue ) - obj["chainwork"] = RPCObject( chainwork ) - obj["nTx"] = RPCObject( String(format: "0x%1x", arguments: [nTx]) ) - obj["previousblockhash"] = RPCObject( previousblockhash ) - obj["nextblockhash"] = RPCObject( nextblockhash ) - return obj - } - - /// initialize the BtcblockWithTx - /// - /// - Parameter hash : the block hash (same as provided) - /// - Parameter confirmations : The number of confirmations, or -1 if the block is not on the main chain - /// - Parameter height : The block height or index - /// - Parameter version : The block version - /// - Parameter versionHex : The block version formatted in hexadecimal - /// - Parameter merkleroot : The merkle root ( 32 bytes ) - /// - Parameter time : The block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter mediantime : The median block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter nonce : The nonce - /// - Parameter bits : The bits ( 4 bytes as hex) representing the target - /// - Parameter difficulty : The difficulty - /// - Parameter chainwork : Expected number of hashes required to produce the current chain (in hex) - /// - Parameter nTx : The number of transactions in the block. - /// - Parameter tx : the array of transactions either as ids (verbose=1) or full transaction (verbose=2) - /// - Parameter previousblockhash : The hash of the previous block - /// - Parameter nextblockhash : The hash of the next block - public init(hash: String, confirmations: Int, height: UInt64, version: Int, versionHex: String, merkleroot: String, time: UInt64, mediantime: UInt64, nonce: UInt64, bits: String, difficulty: UInt256, chainwork: String, nTx: Int, tx: [Btctransaction], previousblockhash: String, nextblockhash: String) { - self.hash = hash - self.confirmations = confirmations - self.height = height - self.version = version - self.versionHex = versionHex - self.merkleroot = merkleroot - self.time = time - self.mediantime = mediantime - self.nonce = nonce - self.bits = bits - self.difficulty = difficulty - self.chainwork = chainwork - self.nTx = nTx - self.tx = tx - self.previousblockhash = previousblockhash - self.nextblockhash = nextblockhash - } -} - -/// the array of transactions either as ids (verbose=1) or full transaction (verbose=2) -public struct Btctransaction { - /// txid - public var txid: String - - /// Whether specified block is in the active chain or not (only present with explicit "blockhash" argument) - public var in_active_chain: Bool - - /// The serialized, hex-encoded data for `txid` - public var hex: String - - /// The transaction hash (differs from txid for witness transactions) - public var hash: String - - /// The serialized transaction size - public var size: UInt64 - - /// The virtual transaction size (differs from size for witness transactions) - public var vsize: UInt64 - - /// The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) - public var weight: UInt64 - - /// The version - public var version: Int - - /// The lock time - public var locktime: UInt64 - - /// array of json objects of incoming txs to be used - public var vin: [BtcVin] - - /// array of json objects describing the tx outputs - public var vout: [BtcVout] - - /// the block hash - public var blockhash: String - - /// The confirmations - public var confirmations: Int - - /// The block time in seconds since epoch (Jan 1 1970 GMT) - public var blocktime: UInt64 - - /// Same as "blocktime" - public var time: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - txid = try toString(obj["txid"],false)! - in_active_chain = try toBool(obj["in_active_chain"],false)! - hex = try toString(obj["hex"],false)! - hash = try toString(obj["hash"],false)! - size = try toUInt64(obj["size"],false)! - vsize = try toUInt64(obj["vsize"],false)! - weight = try toUInt64(obj["weight"],false)! - version = try toInt(obj["version"],false)! - locktime = try toUInt64(obj["locktime"],false)! - vin = try toArray(obj["vin"])!.map({ try BtcVin($0,false)! }) - vout = try toArray(obj["vout"])!.map({ try BtcVout($0,false)! }) - blockhash = try toString(obj["blockhash"],false)! - confirmations = try toInt(obj["confirmations"],false)! - blocktime = try toUInt64(obj["blocktime"],false)! - time = try toUInt64(obj["time"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["txid"] = RPCObject( txid ) - obj["in_active_chain"] = RPCObject( in_active_chain ) - obj["hex"] = RPCObject( hex ) - obj["hash"] = RPCObject( hash ) - obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) - obj["vsize"] = RPCObject( String(format: "0x%1x", arguments: [vsize]) ) - obj["weight"] = RPCObject( String(format: "0x%1x", arguments: [weight]) ) - obj["version"] = RPCObject( String(format: "0x%1x", arguments: [version]) ) - obj["locktime"] = RPCObject( String(format: "0x%1x", arguments: [locktime]) ) - obj["blockhash"] = RPCObject( blockhash ) - obj["confirmations"] = RPCObject( String(format: "0x%1x", arguments: [confirmations]) ) - obj["blocktime"] = RPCObject( String(format: "0x%1x", arguments: [blocktime]) ) - obj["time"] = RPCObject( String(format: "0x%1x", arguments: [time]) ) - return obj - } - - /// initialize the Btctransaction - /// - /// - Parameter txid : txid - /// - Parameter in_active_chain : Whether specified block is in the active chain or not (only present with explicit "blockhash" argument) - /// - Parameter hex : The serialized, hex-encoded data for `txid` - /// - Parameter hash : The transaction hash (differs from txid for witness transactions) - /// - Parameter size : The serialized transaction size - /// - Parameter vsize : The virtual transaction size (differs from size for witness transactions) - /// - Parameter weight : The transaction's weight (between `vsize`\*4-3 and `vsize`\*4) - /// - Parameter version : The version - /// - Parameter locktime : The lock time - /// - Parameter vin : array of json objects of incoming txs to be used - /// - Parameter vout : array of json objects describing the tx outputs - /// - Parameter blockhash : the block hash - /// - Parameter confirmations : The confirmations - /// - Parameter blocktime : The block time in seconds since epoch (Jan 1 1970 GMT) - /// - Parameter time : Same as "blocktime" - public init(txid: String, in_active_chain: Bool, hex: String, hash: String, size: UInt64, vsize: UInt64, weight: UInt64, version: Int, locktime: UInt64, vin: [BtcVin], vout: [BtcVout], blockhash: String, confirmations: Int, blocktime: UInt64, time: UInt64) { - self.txid = txid - self.in_active_chain = in_active_chain - self.hex = hex - self.hash = hash - self.size = size - self.vsize = vsize - self.weight = weight - self.version = version - self.locktime = locktime - self.vin = vin - self.vout = vout - self.blockhash = blockhash - self.confirmations = confirmations - self.blocktime = blocktime - self.time = time - } -} - -/// array of json objects of incoming txs to be used -public struct BtcVin { - /// the transaction id - public var txid: String - - /// the index of the transaction out to be used - public var vout: UInt64 - - /// the script - public var scriptSig: BtcScriptSig - - /// The script sequence number - public var sequence: UInt64 - - /// hex-encoded witness data (if any) - public var txinwitness: [String] - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - txid = try toString(obj["txid"],false)! - vout = try toUInt64(obj["vout"],false)! - scriptSig = try BtcScriptSig(obj["scriptSig"],false)! - sequence = try toUInt64(obj["sequence"],false)! - txinwitness = try toArray(obj["txinwitness"])!.map({ try toString($0,false)! }) - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["txid"] = RPCObject( txid ) - obj["vout"] = RPCObject( String(format: "0x%1x", arguments: [vout]) ) - obj["sequence"] = RPCObject( String(format: "0x%1x", arguments: [sequence]) ) - obj["txinwitness"] = RPCObject( txinwitness ) - return obj - } - - /// initialize the BtcVin - /// - /// - Parameter txid : the transaction id - /// - Parameter vout : the index of the transaction out to be used - /// - Parameter scriptSig : the script - /// - Parameter sequence : The script sequence number - /// - Parameter txinwitness : hex-encoded witness data (if any) - public init(txid: String, vout: UInt64, scriptSig: BtcScriptSig, sequence: UInt64, txinwitness: [String]) { - self.txid = txid - self.vout = vout - self.scriptSig = scriptSig - self.sequence = sequence - self.txinwitness = txinwitness - } -} - -/// the script -public struct BtcScriptSig { - /// the asm-codes - public var asm: String - - /// hex representation - public var hex: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - asm = try toString(obj["asm"],false)! - hex = try toString(obj["hex"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["asm"] = RPCObject( asm ) - obj["hex"] = RPCObject( hex ) - return obj - } - - /// initialize the BtcScriptSig - /// - /// - Parameter asm : the asm-codes - /// - Parameter hex : hex representation - public init(asm: String, hex: String) { - self.asm = asm - self.hex = hex - } -} - -/// array of json objects describing the tx outputs -public struct BtcVout { - /// The Value in BTC - public var value: Double - - /// the index - public var n: Int - - /// the script pubkey - public var scriptPubKey: BtcScriptPubKey - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - value = try toDouble(obj["value"],false)! - n = try toInt(obj["n"],false)! - scriptPubKey = try BtcScriptPubKey(obj["scriptPubKey"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["value"] = RPCObject( value ) - obj["n"] = RPCObject( String(format: "0x%1x", arguments: [n]) ) - return obj - } - - /// initialize the BtcVout - /// - /// - Parameter value : The Value in BTC - /// - Parameter n : the index - /// - Parameter scriptPubKey : the script pubkey - public init(value: Double, n: Int, scriptPubKey: BtcScriptPubKey) { - self.value = value - self.n = n - self.scriptPubKey = scriptPubKey - } -} - -/// the script pubkey -public struct BtcScriptPubKey { - /// asm - public var asm: String - - /// hex representation of the script - public var hex: String - - /// the required signatures - public var reqSigs: Int - - /// The type, eg 'pubkeyhash' - public var type: String - - /// Array of address(each representing a bitcoin adress) - public var addresses: [String] - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - asm = try toString(obj["asm"],false)! - hex = try toString(obj["hex"],false)! - reqSigs = try toInt(obj["reqSigs"],false)! - type = try toString(obj["type"],false)! - addresses = try toArray(obj["addresses"])!.map({ try toString($0,false)! }) - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["asm"] = RPCObject( asm ) - obj["hex"] = RPCObject( hex ) - obj["reqSigs"] = RPCObject( String(format: "0x%1x", arguments: [reqSigs]) ) - obj["type"] = RPCObject( type ) - obj["addresses"] = RPCObject( addresses ) - return obj - } - - /// initialize the BtcScriptPubKey - /// - /// - Parameter asm : asm - /// - Parameter hex : hex representation of the script - /// - Parameter reqSigs : the required signatures - /// - Parameter type : The type, eg 'pubkeyhash' - /// - Parameter addresses : Array of address(each representing a bitcoin adress) - public init(asm: String, hex: String, reqSigs: Int, type: String, addresses: [String]) { - self.asm = asm - self.hex = hex - self.reqSigs = reqSigs - self.type = type - self.addresses = addresses - } -} - -/// A path of daps from the `verified_dap` to the `target_dap` which fulfils the conditions of `max_diff`, `max_dap` and `limit`. Each dap of the path is a `dap`-object with corresponding proof data. -public struct BtcProofTarget { - /// the difficulty adjustement period - public var dap: UInt64 - - /// the first blockheader - public var block: String - - /// the finality header - public var final: String - - /// the coinbase transaction as hex - public var cbtx: String - - /// the coinbasetx merkle proof - public var cbtxMerkleProof: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - dap = try toUInt64(obj["dap"],false)! - block = try toString(obj["block"],false)! - final = try toString(obj["final"],false)! - cbtx = try toString(obj["cbtx"],false)! - cbtxMerkleProof = try toString(obj["cbtxMerkleProof"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["dap"] = RPCObject( String(format: "0x%1x", arguments: [dap]) ) - obj["block"] = RPCObject( block ) - obj["final"] = RPCObject( final ) - obj["cbtx"] = RPCObject( cbtx ) - obj["cbtxMerkleProof"] = RPCObject( cbtxMerkleProof ) - return obj - } - - /// initialize the BtcProofTarget - /// - /// - Parameter dap : the difficulty adjustement period - /// - Parameter block : the first blockheader - /// - Parameter final : the finality header - /// - Parameter cbtx : the coinbase transaction as hex - /// - Parameter cbtxMerkleProof : the coinbasetx merkle proof - public init(dap: UInt64, block: String, final: String, cbtx: String, cbtxMerkleProof: String) { - self.dap = dap - self.block = block - self.final = final - self.cbtx = cbtx - self.cbtxMerkleProof = cbtxMerkleProof - } -} \ No newline at end of file diff --git a/swift/Sources/In3/API/Contract.swift b/swift/Sources/In3/API/Contract.swift deleted file mode 100644 index 8feaa825e..000000000 --- a/swift/Sources/In3/API/Contract.swift +++ /dev/null @@ -1,371 +0,0 @@ -// -// File.swift -// -// -// Created by Simon Jentzsch on 09.04.21. -// - -import Foundation - -internal func toHex(val:AnyObject, len:Int=0) -> String { - var s="" - switch val { - case let val as UInt64: - s = String(format: "%1x", arguments: [val]) - case let val as Int: - s = String(format: "%1x", arguments: [val]) - case let val as Double: - s = UInt256(String(val))?.toString(radix: 16) ?? "" - case let val as String: - s = val.replacingOccurrences(of: "0x", with: "") - case let val as Bool: - s = val ? "1" : "0" - case nil: - s = "" - default: - s = "" - } - while s.count < len*2 { - s = "0" + s - } - return "0x" + s -} - -/// represents a contract with a defined ABI -/// for the ABI-spec see https://docs.soliditylang.org/en/v0.7.4/abi-spec.html?highlight=JSON#json -public class Contract { - - var in3:In3 - var address:String? - var abi:[ABI] - var hashes:[String:ABI] - - /// creates a new Contract-Instance - /// you need to specify either the abi or the abiJson-Property. - /// - Parameter in3 : the Incubed instance - /// - Parameter abi : the parsed structuured ABI-Definitions - /// - Parameter abiJSON : the ABI as JSON-String - /// - Parameter at : address of the deployed contract - /// - public init(in3:In3, abi:[ABI]? = nil, abiJSON:String? = nil, at: String?=nil) throws { - self.in3=in3 - self.address = at - self.hashes = [:] - if let x = abi { - self.abi=x - } else if let json = abiJSON { - self.abi = try JSONDecoder().decode([ABI].self, from: json.data(using: .utf8)!) - } else { - throw IncubedError.config(message: "No ABI given!") - } - let utils = Utils(in3) - for var a in self.abi { - let hash = try utils.keccak(data: a.inputSignature.replacingOccurrences(of: "indexed ", with: "")) - self.hashes[hash] = a - a.hash = hash - } - } - - /// deploys the contract and returns the transactionhash - /// - Parameter data : the bytes as hex of the code to deploy - /// - Parameter args : the optional arguments of the constructor - /// - Parameter account : the account to send the transaction from - /// - Parameter gas : the amount of gas to be used - /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. - /// - /// - Returns : The TransactionHash - public func deploy(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { - do { - return Eth(in3).sendTransaction(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)) - } catch { - let p = Promise() - p.reject(with: error) - return p - } - } - - /// deploys the contract and wait until the receipt is available. - /// - Parameter data : the bytes as hex of the code to deploy - /// - Parameter args : the optional arguments of the constructor - /// - Parameter account : the account to send the transaction from - /// - Parameter gas : the amount of gas to be used - /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. - /// - /// - Returns : The TransactionReceipt - public func deployAndWait(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { - do { - return Eth(in3).sendTransactionAndWait(tx: try createDeployTx(data: data, args: args, account: account, gas: gas, gasPrice: gasPrice)).chained(using: { - self.address = $0.contractAddress - return Promise(value:$0) - }) - } catch { - let p = Promise() - p.reject(with: error) - return p - } - } - - /// create a TransactionDefinition which cqan be used to deploy the contract - /// - Parameter data : the bytes as hex of the code to deploy - /// - Parameter args : the optional arguments of the constructor - /// - Parameter account : the account to send the transaction from - /// - Parameter gas : the amount of gas to be used - /// - Parameter gasPrice : the gasPrice. If not given the current gasPrice will be used. - /// - /// - Returns : The Transaction Definition - public func createDeployTx(data: String, args: [AnyObject]?=nil, account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { - if let x = args, x.count>0 { - var tx = try createTx(name: "", args: x, account: account, gas: gas, gasPrice: gasPrice) - tx.data = data + String(tx.data!.suffix(from: tx.data!.index(tx.data!.startIndex, offsetBy: 10))) - return tx - } else { - return EthTransaction( from: account, gas: gas, gasPrice: gasPrice,data : data) - } - } - - /// calls a function of the contract by running the code in a local evm. - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - Parameter account : the account to be used as sender - /// - Parameter gas : the amount of gas to be used as limit - /// - /// - Returns : a array witht the return values of the function - public func call(name: String, args: [AnyObject], block: UInt64? = nil, account:String?=nil, gas: UInt64?=nil) -> Future<[Any]> { - do { - let tx = try createTx(name: name, args: args, account: account, gas: gas) - return Eth(in3).call(tx: tx, block: block).chained(using: { - let res = try Utils(self.in3).abiDecode(signature: self[name]!.signature, data : $0) - return Promise(value: res.map({ $0.asObject() }) as [Any]) - }) - } catch { - let p = Promise<[Any]>() - p.reject(with: error) - return p - } - } - - /// estimates the gas used to send a transaction to the specified function of the contract. - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - Parameter account : the account to be used as sender - /// - /// - Returns :the gas needed to run a tx - public func estimateGas(name: String, args: [AnyObject], account:String?=nil) -> Future { - do { - let tx = try createTx(name: name, args: args, account: account) - return Eth(in3).estimateGas(tx: tx) - } catch { - let p = Promise() - p.reject(with: error) - return p - } - } - - /// sends a transaction to a function of the contract and returns the transactionHash - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - Parameter account : the account to be used as sender - /// - Parameter gas : the amount of gas to be used as limit - /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. - /// - /// - Returns : the TransactionHash - public func sendTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { - do { - return Eth(in3).sendTransaction(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) - } catch { - let p = Promise() - p.reject(with: error) - return p - } - } - - /// sends a transaction to a function of the contract and waits for the receipt. - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - Parameter account : the account to be used as sender - /// - Parameter gas : the amount of gas to be used as limit - /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. - /// - /// - Returns : the TransactionReceipt - public func sendTxAndWait(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) -> Future { - do { - return Eth(in3).sendTransactionAndWait(tx: try createTx(name: name, args: args, account: account, gas: gas, gasPrice: gasPrice)) - } catch { - let p = Promise() - p.reject(with: error) - return p - } - } - - /// returns the abi encoded arguments as hex string - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - /// - Returns : the abi encoded arguments as hex string - public func encodeCall(name: String, args: [AnyObject]) throws -> String{ - if let abi = self[name] { - return try Utils(in3).abiEncode(signature: abi.signature, params: args) - } else { - throw IncubedError.rpc(message: "The method \(name) does not exist in the contract!") - } - } - - - /// creates the transaction parameter for a tx to the given function. - /// - Parameter name : the name of the function - /// - Parameter args : the arguments. - /// - Parameter account : the account to be used as sender - /// - Parameter gas : the amount of gas to be used as limit - /// - Parameter gasPrice : the gasPrice. if not set, the current average gasPrice will be used. - /// - /// - Returns : the EthTransaction with the set parameters - public func createTx(name: String, args: [AnyObject], account:String?=nil, gas: UInt64?=nil, gasPrice: UInt64?=nil) throws -> EthTransaction { - if let adr = address { - let data = try encodeCall(name: name, args: args) - return EthTransaction(to: adr, from: account, gas: gas ?? 100000, gasPrice: gasPrice, data: data) - } else { - throw IncubedError.config(message: "The Contract has no address!") - } - } - - /// reads events for the given contract - /// if the eventName is omitted all events will be returned. ( in this case filter must be nil ! ) - /// - Parameter eventName : the name of the event or null if all events should be fetched - /// - Parameter filter : the dictionary with values to search for. Only valid if the eventName is set and the all values must be indexed arguments! - /// - Parameter fromBlock : the BlockNumber to start searching for events. If nil the latest block is used. - /// - Parameter toBlock : the BlockNumber to end searching for events. If nil the latest block is used. - /// - Parameter topics : the topics of the block as search criteria. - public func getEvents(eventName:String? = nil, filter: [String:AnyObject]? = nil, fromBlock: UInt64? = nil, toBlock: UInt64? = nil, topics: [String?]?) -> Future<[EthEvent]> { - do { - var t = [String?].init(repeating: nil, count: 4) - if let x = topics { - var i = 0 - for n in x { - t[i] = n - i += 1 - } - } - if let name = eventName { - if filter != nil { - throw IncubedError.config(message: "filter is not allowed when fetiching all event!") - } - guard let def = self[name], let inp = def.inputs else { - throw IncubedError.config(message: "The event \(name) does not exist in the abi definition!") - } - t[0] = def.hash - - if let f = filter { - var i = 0 - for d in inp { - if let x = d.indexed, x { - i += 1 - if let val = f[d.name] { - t[i] = toHex(val: val, len:32) - } - } - } - } - } - - let ef = EthFilter(fromBlock: fromBlock, toBlock: toBlock, address: self.address, topics: t) - return Eth(in3).getLogs(filter: ef).chained(using: { - Promise<[EthEvent]>(value: try $0.map({ (log) -> EthEvent in - if let abi = self.hashes[log.topics[0]] { - return try EthEvent(in3: self.in3, abi: abi, log: log) - } else { - throw IncubedError.config(message: "The eventhash \(log.topics[0]) can not be found in the config!") - } - })) - }) - } catch { - let p = Promise<[EthEvent]>() - p.reject(with: error) - return p - } - } - - - /// accesses the ABI for the given function or event - /// - Parameter name : the name to search for - subscript(name: String) -> ABI? { - get { - return self.abi.first(where:{ $0.name == name }) - } - } -} - - - -/// a function, event or a -public struct ABI : Codable { - public var hash:String? - public var anonymous: Bool? - public var constant: Bool? - public var payable: Bool? - public var stateMutability: String? - public var components: [ABIField]? - public var inputs: [ABIField]? - public var outputs: [ABIField]? - public var name: String? - public var type: String - public var internalType: String? - public var signature:String { - if let r = outputs { - return inputSignature + ":(\( r.map({ $0.signature }).joined(separator: ",") ))" - } else { - return inputSignature - } - } - public var inputSignature:String { - guard let inp = inputs, let name = self.name else { - return "\(self.name ?? "_")()" - } - return "\(name == "" ? "_" : name)(\( inp.map({ $0.signature }).joined(separator: ",") ))" - } -} - - -/// configure the Bitcoin verification -public struct ABIField : Codable { - public var internalType: String? - public var components: [ABIField]? - public var indexed: Bool? - public var name: String - public var type: String - public var signature:String { - let parts = type.split(separator: "[", maxSplits: 2) - var baseType = String(parts[0]) - let array = parts.count == 2 ? String(parts[1]) : "" - - if baseType == "tuple", let cs = components { - baseType = "(\(cs.map({ $0.signature }).joined(separator: ",")))" - } - if let x = indexed, x { - return "indexed " + baseType - } - return baseType + array - } -} - - -public struct EthEvent { - public var log:Ethlog - public var event:String - public var values:[String:AnyObject] - - init(in3:In3, abi:ABI, log:Ethlog) throws { - self.log = log - self.event = abi.name ?? "" - self.values = [:] - if let inp = abi.inputs { - let vals = try Utils(in3).abiDecode(signature: abi.inputSignature, data: log.data, topics: "0x"+log.topics.map({ $0.replacingOccurrences(of: "0x", with: "")}).joined(separator: "")) - var i = 0 - for a in inp { - let r = vals[i] - self.values[a.name] = r.asObject() - i += 1 - } - } - } - -} diff --git a/swift/Sources/In3/API/Eth.swift b/swift/Sources/In3/API/Eth.swift deleted file mode 100644 index e1b82b5d1..000000000 --- a/swift/Sources/In3/API/Eth.swift +++ /dev/null @@ -1,1346 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// Standard JSON-RPC calls as described in https://eth.wiki/json-rpc/API. -/// -/// Whenever a request is made for a response with `verification`: `proof`, the node must provide the proof needed to validate the response result. The proof itself depends on the chain. -/// -/// For ethereum, all proofs are based on the correct block hash. That's why verification differentiates between [Verifying the blockhash](poa.html) (which depends on the user consensus) the actual result data. -/// -/// There is another reason why the BlockHash is so important. This is the only value you are able to access from within a SmartContract, because the evm supports a OpCode (`BLOCKHASH`), which allows you to read the last 256 blockhashes, which gives us the chance to verify even the blockhash onchain. -/// -/// Depending on the method, different proofs are needed, which are described in this document. -/// -/// Proofs will add a special in3-section to the response containing a `proof`- object. Each `in3`-section of the response containing proofs has a property with a proof-object with the following properties: -/// -/// * **type** `string` (required) - The type of the proof. -/// Must be one of the these values : `'transactionProof`', `'receiptProof`', `'blockProof`', `'accountProof`', `'callProof`', `'logProof`' -/// * **block** `string` - The serialized blockheader as hex, required in most proofs. -/// * **finalityBlocks** `array` - The serialized following blockheaders as hex, required in case of finality asked (only relevant for PoA-chains). The server must deliver enough blockheaders to cover more then 50% of the validators. In order to verify them, they must be linkable (with the parentHash). -/// * **transactions** `array` - The list of raw transactions of the block if needed to create a merkle trie for the transactions. -/// * **uncles** `array` - The list of uncle-headers of the block. This will only be set if full verification is required in order to create a merkle tree for the uncles and so prove the uncle_hash. -/// * **merkleProof** `string[]` - The serialized merkle-nodes beginning with the root-node (depending on the content to prove). -/// * **merkleProofPrev** `string[]` - The serialized merkle-nodes beginning with the root-node of the previous entry (only for full proof of receipts). -/// * **txProof** `string[]` - The serialized merkle-nodes beginning with the root-node in order to proof the transactionIndex (only needed for transaction receipts). -/// * **logProof** [LogProof](#logproof) - The Log Proof in case of a `eth_getLogs`-request. -/// * **accounts** `object` - A map of addresses and their AccountProof. -/// * **txIndex** `integer` - The transactionIndex within the block (for transaactions and receipts). -/// * **signatures** `Signature[]` - Requested signatures. -/// -public class Eth { - internal var in3: In3 - - /// initialiazes the Eth API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// returns the number of the most recent block. - /// - /// See [eth_blockNumber](https://eth.wiki/json-rpc/API#eth_blockNumber) for spec. - /// - /// No proof returned, since there is none, but the client should verify the result by comparing it to the current blocks returned from others. - /// With the `blockTime` from the chainspec, including a tolerance, the current blocknumber may be checked if in the proposed range. - /// - /// - Returns: the highest known blocknumber - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).blockNumber() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xb8a2a5" - /// } - /// } - /// - /// ``` - /// - public func blockNumber() -> Future { - return execAndConvert(in3: in3, method: "eth_blockNumber", convertWith: toUInt64 ) - } - - /// returns the given Block by number with transactionHashes. if no blocknumber is specified the latest block will be returned. - /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` - /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getBlock() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // author: "0x0000000000000000000000000000000000000000" - /// // difficulty: "0x2" - /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 - /// // gasLimit: "0x7a1200" - /// // gasUsed: "0x20e145" - /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" - /// // logsBloom: 0x000008000000000000...00400100000000080 - /// // miner: "0x0000000000000000000000000000000000000000" - /// // number: "0x449956" - /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" - /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" - /// // sealFields: - /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" - /// // - "0x880000000000000000" - /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - /// // size: "0x74b" - /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" - /// // timestamp: "0x605aec86" - /// // totalDifficulty: "0x6564de" - /// // transactions: - /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" - /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" - /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" - /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" - /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" - /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" - /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" - /// // uncles: [] - /// } - /// } - /// - /// ``` - /// - public func getBlock(blockNumber: UInt64? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber", params:blockNumber == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", blockNumber!) ), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) - } - - /// returns the given Block by number with full transaction data. if no blocknumber is specified the latest block will be returned. - /// - Parameter blockNumber : the blockNumber or one of `latest`, `earliest`or `pending` - /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getBlockWithTx() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // author: "0x0000000000000000000000000000000000000000" - /// // difficulty: "0x2" - /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 - /// // gasLimit: "0x7a1200" - /// // gasUsed: "0x20e145" - /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" - /// // logsBloom: 0x000008000000000000...00400100000000080 - /// // miner: "0x0000000000000000000000000000000000000000" - /// // number: "0x449956" - /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" - /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" - /// // sealFields: - /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" - /// // - "0x880000000000000000" - /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - /// // size: "0x74b" - /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" - /// // timestamp: "0x605aec86" - /// // totalDifficulty: "0x6564de" - /// // transactions: - /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" - /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" - /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" - /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" - /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" - /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" - /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" - /// // uncles: [] - /// } - /// } - /// - /// ``` - /// - public func getBlockWithTx(blockNumber: UInt64? = nil) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByNumber", params:blockNumber == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", blockNumber!) ), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) - } - - /// returns the given Block by hash with transactionHashes - /// - Parameter blockHash : the blockHash of the block - /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getBlockByHash(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // author: "0x0000000000000000000000000000000000000000" - /// // difficulty: "0x2" - /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 - /// // gasLimit: "0x7a1200" - /// // gasUsed: "0x20e145" - /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" - /// // logsBloom: 0x000008000000000000...00400100000000080 - /// // miner: "0x0000000000000000000000000000000000000000" - /// // number: "0x449956" - /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" - /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" - /// // sealFields: - /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" - /// // - "0x880000000000000000" - /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - /// // size: "0x74b" - /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" - /// // timestamp: "0x605aec86" - /// // totalDifficulty: "0x6564de" - /// // transactions: - /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" - /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" - /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" - /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" - /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" - /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" - /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" - /// // uncles: [] - /// } - /// } - /// - /// ``` - /// - public func getBlockByHash(blockHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash", params:RPCObject( blockHash), RPCObject(false), convertWith: { try EthBlockdataWithTxHashes($0,$1) } ) - } - - /// returns the given Block by hash with full transaction data - /// - Parameter blockHash : the blockHash of the block - /// - Returns: the blockdata, or in case the block with that number does not exist, `null` will be returned. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getBlockByHashWithTx(blockHash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // author: "0x0000000000000000000000000000000000000000" - /// // difficulty: "0x2" - /// // extraData: 0x696e667572612d696f0000000000000...31570f1e500 - /// // gasLimit: "0x7a1200" - /// // gasUsed: "0x20e145" - /// // hash: "0x2baa54adcd8a105cdedfd9c6635d48d07b8f0e805af0a5853190c179e5a18585" - /// // logsBloom: 0x000008000000000000...00400100000000080 - /// // miner: "0x0000000000000000000000000000000000000000" - /// // number: "0x449956" - /// // parentHash: "0x2c2a4fcd11aa9aea6b9767651a10e7dbd2bcddbdaba703c74458ad6faf7c2694" - /// // receiptsRoot: "0x0240b90272b5600bef7e25d0894868f85125174c2f387ef3236fc9ed9bfb3eff" - /// // sealFields: - /// // - "0xa00000000000000000000000000000000000000000000000000000000000000000" - /// // - "0x880000000000000000" - /// // sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - /// // size: "0x74b" - /// // stateRoot: "0xf44699575afd2668060be5ba77e66e1e80edb77ad1b5070969ddfa63da6a4910" - /// // timestamp: "0x605aec86" - /// // totalDifficulty: "0x6564de" - /// // transactions: - /// // - "0xcb7edfdb3229c9beeb418ab1ef1a3c9210ecfb22f0157791c3287085d798da58" - /// // - "0x0fb803696521ba109c40b3eecb773c93dc6ee891172af0f620c8d44c05198641" - /// // - "0x3ef6725cab4470889c3c7d53609a5d4b263701f5891aa98c9ed48b73b6b2fb75" - /// // - "0x4010c4c112514756dcdcf14f91117503826dcbe15b03a1636c07aa713da24b8d" - /// // - "0xd9c14daa5e2e9cc955534865365ef6bde3045c70e3a984a74c298606c4d67bb5" - /// // - "0xfa2326237ba5dcca2127241562be16b68c48fed93d29add8d62f79a00518c2d8" - /// // transactionsRoot: "0xddbbd7bf723abdfe885539406540671c2c0eb97684972175ad199258c75416cc" - /// // uncles: [] - /// } - /// } - /// - /// ``` - /// - public func getBlockByHashWithTx(blockHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getBlockByHash", params:RPCObject( blockHash), RPCObject(false), convertWith: { try EthBlockdata($0,$1) } ) - } - - /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByHash](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByHash). - /// - Parameter blockHash : the blockHash of the block - /// - Returns: the number of transactions in the block - public func getBlockTransactionCountByHash(blockHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByHash", params:RPCObject( blockHash), convertWith: toString ) - } - - /// returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByNumber). - /// - Parameter blockNumber : the blockNumber of the block - /// - Returns: the number of transactions in the block - public func getBlockTransactionCountByNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getBlockTransactionCountByNumber", params:RPCObject( String(format: "0x%1x", blockNumber)), convertWith: toString ) - } - - /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). - /// - Parameter blockHash : the blockHash of the block - /// - Returns: the number of uncles - public func getUncleCountByBlockHash(blockHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockHash", params:RPCObject( blockHash), convertWith: toString ) - } - - /// returns the number of uncles. For Spec, see [eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockNumber). - /// - Parameter blockNumber : the blockNumber of the block - /// - Returns: the number of uncles - public func getUncleCountByBlockNumber(blockNumber: UInt64) -> Future { - return execAndConvert(in3: in3, method: "eth_getUncleCountByBlockNumber", params:RPCObject( String(format: "0x%1x", blockNumber)), convertWith: toString ) - } - - /// returns the transaction data. - /// - /// See JSON-RPC-Spec for [eth_getTransactionByBlockHashAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockHashAndIndex) for more details. - /// - /// - Parameter blockHash : the blockhash containing the transaction. - /// - Parameter index : the transactionIndex - /// - Returns: the transactiondata or `null` if it does not exist - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getTransactionByBlockHashAndIndex(blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee", index: "0xd5") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" - /// // blockNumber: "0xb8a4a9" - /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" - /// // gas: "0xac6b" - /// // gasPrice: "0x1bf08eb000" - /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" - /// // input: 0x095ea7b300000000000000000000000...a7640000 - /// // nonce: "0xa" - /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" - /// // transactionIndex: "0xd5" - /// // value: "0x0" - /// // type: "0x0" - /// // v: "0x25" - /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" - /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" - /// } - /// } - /// - /// ``` - /// - public func getTransactionByBlockHashAndIndex(blockHash: String, index: Int) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockHashAndIndex", params:RPCObject( blockHash), RPCObject( String(format: "0x%1x", index)), convertWith: { try EthTransactiondata($0,$1) } ) - } - - /// returns the transaction data. - /// - /// See JSON-RPC-Spec for [eth_getTransactionByBlockNumberAndIndex](https://eth.wiki/json-rpc/API#eth_getTransactionByBlockNumberAndIndex) for more details. - /// - /// - Parameter blockNumber : the block number containing the transaction. - /// - Parameter index : the transactionIndex - /// - Returns: the transactiondata or `null` if it does not exist - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getTransactionByBlockNumberAndIndex(blockNumber: "0xb8a4a9", index: "0xd5") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" - /// // blockNumber: "0xb8a4a9" - /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" - /// // gas: "0xac6b" - /// // gasPrice: "0x1bf08eb000" - /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" - /// // input: 0x095ea7b300000000000000000000000...a7640000 - /// // nonce: "0xa" - /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" - /// // transactionIndex: "0xd5" - /// // value: "0x0" - /// // type: "0x0" - /// // v: "0x25" - /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" - /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" - /// } - /// } - /// - /// ``` - /// - public func getTransactionByBlockNumberAndIndex(blockNumber: UInt64, index: Int) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByBlockNumberAndIndex", params:RPCObject( String(format: "0x%1x", blockNumber)), RPCObject( String(format: "0x%1x", index)), convertWith: { try EthTransactiondata($0,$1) } ) - } - - /// returns the transaction data. - /// - /// See JSON-RPC-Spec for [eth_getTransactionByHash](https://eth.wiki/json-rpc/API#eth_getTransactionByHash) for more details. - /// - /// - Parameter txHash : the transactionHash of the transaction. - /// - Returns: the transactiondata or `null` if it does not exist - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getTransactionByHash(txHash: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // blockHash: "0x4fc08daf8d670a23eba7a1aca1f09591c19147305c64d25e1ddd3dd43ff658ee" - /// // blockNumber: "0xb8a4a9" - /// // from: "0xcaa6cfc2ca92cabbdbce5a46901ee8b831e00a98" - /// // gas: "0xac6b" - /// // gasPrice: "0x1bf08eb000" - /// // hash: "0xd635a97452d604f735116d9de29ac946e9987a20f99607fb03516ef267ea0eea" - /// // input: 0x095ea7b300000000000000000000000...a7640000 - /// // nonce: "0xa" - /// // to: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" - /// // transactionIndex: "0xd5" - /// // value: "0x0" - /// // type: "0x0" - /// // v: "0x25" - /// // r: "0xb18e0928c988d898d3217b145d78439072db15ea7de1005a73cf5feaf01a57d4" - /// // s: "0x6b530c2613f543f9e26ef9c27a7986c748fbc856aaeacd6000a8ff46d2a2dd78" - /// } - /// } - /// - /// ``` - /// - public func getTransactionByHash(txHash: String) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionByHash", params:RPCObject( txHash), convertWith: { try EthTransactiondata($0,$1) } ) - } - - /// searches for events matching the given criteria. See [eth_getLogs](https://eth.wiki/json-rpc/API#eth_getLogs) for the spec. - /// - Parameter filter : The filter criteria for the events. - /// - Returns: array with all found event matching the specified filter - public func getLogs(filter: EthFilter) -> Future<[Ethlog]> { - return execAndConvert(in3: in3, method: "eth_getLogs", params:RPCObject( filter.toRPCDict()), convertWith: { try toArray($0,$1)!.map({ try Ethlog($0,false)! }) } ) - } - - /// gets the balance of an account for a given block - /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or `latest` - /// - Returns: the balance - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getBalance(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x20599832af6ec00" - /// } - /// } - /// - /// ``` - /// - public func getBalance(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getBalance", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toUInt256 ) - } - - /// gets the nonce or number of transaction sent from this account at a given block - /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or `latest` - /// - Returns: the nonce - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getTransactionCount(account: "0x2e333ec090f1028df0a3c39a918063443be82b2b") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x5" - /// } - /// } - /// - /// ``` - /// - public func getTransactionCount(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getTransactionCount", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) - } - - /// gets the code of a given contract - /// - Parameter account : address of the account - /// - Parameter block : the blockNumber or `latest` - /// - Returns: the code as hex - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getCode(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 0x6080604052348...6c634300050a0040 - /// } - /// } - /// - /// ``` - /// - public func getCode(account: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getCode", params:RPCObject( account), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) - } - - /// gets the storage value of a given key - /// - Parameter account : address of the account - /// - Parameter key : key to look for - /// - Parameter block : the blockNumber or`latest` - /// - Returns: the value of the storage slot. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getStorageAt(account: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f", key: "0x0") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x19" - /// } - /// } - /// - /// ``` - /// - public func getStorageAt(account: String, key: String, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_getStorageAt", params:RPCObject( account), RPCObject( key), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) - } - - /// signs and sends a Transaction - /// - Parameter tx : the transactiondata to send - /// - Returns: the transactionHash - public func sendTransaction(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_sendTransaction", params:RPCObject( tx.toRPCDict()), convertWith: toString ) - } - - /// signs and sends a Transaction, but then waits until the transaction receipt can be verified. Depending on the finality of the nodes, this may take a while, since only final blocks will be signed by the nodes. - /// - Parameter tx : the transactiondata to send - /// - Returns: the transactionReceipt - public func sendTransactionAndWait(tx: EthTransaction) -> Future { - return execAndConvert(in3: in3, method: "eth_sendTransactionAndWait", params:RPCObject( tx.toRPCDict()), convertWith: { try EthTransactionReceipt($0,$1) } ) - } - - /// sends or broadcasts a prviously signed raw transaction. See [eth_sendRawTransaction](https://eth.wiki/json-rpc/API#eth_sendRawTransaction) - /// - Parameter tx : the raw signed transactiondata to send - /// - Returns: the transactionhash - public func sendRawTransaction(tx: String) -> Future { - return execAndConvert(in3: in3, method: "eth_sendRawTransaction", params:RPCObject( tx), convertWith: toString ) - } - - /// calculates the gas needed to execute a transaction. for spec see [eth_estimateGas](https://eth.wiki/json-rpc/API#eth_estimateGas) - /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Parameter block : the blockNumber or `latest` - /// - Returns: the amount of gass needed. - public func estimateGas(tx: EthTransaction, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_estimateGas", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toUInt64 ) - } - - /// calls a function of a contract (or simply executes the evm opcodes) and returns the result. for spec see [eth_call](https://eth.wiki/json-rpc/API#eth_call) - /// - Parameter tx : the tx-object, which is the same as specified in [eth_sendTransaction](https://eth.wiki/json-rpc/API#eth_sendTransaction). - /// - Parameter block : the blockNumber or `latest` - /// - Returns: the abi-encoded result of the function. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).call(tx: EthTransaction(to: "0x2736D225f85740f42D17987100dc8d58e9e16252", data: "0x5cf0f3570000000000000000000000000000000000000000000000000000000000000001")) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 0x0000000000000000000000000... - /// } - /// } - /// - /// ``` - /// - public func call(tx: EthTransaction, block: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "eth_call", params:RPCObject( tx.toRPCDict()), block == nil ? RPCObject("latest") : RPCObject( String(format: "0x%1x", block!) ), convertWith: toString ) - } - - /// The Receipt of a Transaction. For Details, see [eth_getTransactionReceipt](https://eth.wiki/json-rpc/API#eth_gettransactionreceipt). - /// - Parameter txHash : the transactionHash - /// - Returns: the TransactionReceipt or `null` if it does not exist. - /// - /// **Example** - /// - /// ```swift - /// Eth(in3).getTransactionReceipt(txHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" - /// // blockNumber: "0x8c1e39" - /// // contractAddress: null - /// // cumulativeGasUsed: "0x2466d" - /// // gasUsed: "0x2466d" - /// // logs: - /// // - address: "0x85ec283a3ed4b66df4da23656d4bf8a507383bca" - /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" - /// // blockNumber: "0x8c1e39" - /// // data: 0x00000000000... - /// // logIndex: "0x0" - /// // removed: false - /// // topics: - /// // - "0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8" - /// // - "0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6" - /// // - "0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000" - /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" - /// // transactionIndex: "0x0" - /// // transactionLogIndex: "0x0" - /// // type: mined - /// // logsBloom: 0x00000000000000000000200000... - /// // root: null - /// // status: "0x1" - /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" - /// // transactionIndex: "0x0" - /// } - /// } - /// - /// ``` - /// - public func getTransactionReceipt(txHash: String) -> Future { - return execAndConvertOptional(in3: in3, method: "eth_getTransactionReceipt", params:RPCObject( txHash), convertWith: { try EthTransactionReceipt($0,$1) } ) - } - - -} -/// the blockdata, or in case the block with that number does not exist, `null` will be returned. -public struct EthBlockdataWithTxHashes { - /// Array of transaction hashes - public var transactions: [String] - - /// the block number. `null` when its pending block. - public var number: UInt64 - - /// hash of the block. `null` when its pending block. - public var hash: String - - /// hash of the parent block. - public var parentHash: String - - /// hash of the generated proof-of-work. `null` when its pending block. - public var nonce: UInt256 - - /// SHA3 of the uncles Merkle root in the block. - public var sha3Uncles: String - - /// the bloom filter for the logs of the block. `null` when its pending block. - public var logsBloom: String - - /// the root of the transaction trie of the block. - public var transactionsRoot: String - - /// the root of the final state trie of the block. - public var stateRoot: String - - /// the root of the receipts trie of the block. - public var receiptsRoot: String - - /// the address of the beneficiary to whom the mining rewards were given. - public var miner: String - - /// integer of the difficulty for this block. - public var difficulty: UInt256 - - /// integer of the total difficulty of the chain until this block. - public var totalDifficulty: UInt256 - - /// the "extra data" field of this block. - public var extraData: String - - /// integer the size of this block in bytes. - public var size: UInt64 - - /// the maximum gas allowed in this block. - public var gasLimit: UInt64 - - /// the total used gas by all transactions in this block. - public var gasUsed: UInt64 - - /// the unix timestamp for when the block was collated. - public var timestamp: UInt64 - - /// Array of uncle hashes. - public var uncles: [String] - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - transactions = try toArray(obj["transactions"])!.map({ try toString($0,false)! }) - number = try toUInt64(obj["number"],false)! - hash = try toString(obj["hash"],false)! - parentHash = try toString(obj["parentHash"],false)! - nonce = try toUInt256(obj["nonce"],false)! - sha3Uncles = try toString(obj["sha3Uncles"],false)! - logsBloom = try toString(obj["logsBloom"],false)! - transactionsRoot = try toString(obj["transactionsRoot"],false)! - stateRoot = try toString(obj["stateRoot"],false)! - receiptsRoot = try toString(obj["receiptsRoot"],false)! - miner = try toString(obj["miner"],false)! - difficulty = try toUInt256(obj["difficulty"],false)! - totalDifficulty = try toUInt256(obj["totalDifficulty"],false)! - extraData = try toString(obj["extraData"],false)! - size = try toUInt64(obj["size"],false)! - gasLimit = try toUInt64(obj["gasLimit"],false)! - gasUsed = try toUInt64(obj["gasUsed"],false)! - timestamp = try toUInt64(obj["timestamp"],false)! - uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["transactions"] = RPCObject( transactions ) - obj["number"] = RPCObject( String(format: "0x%1x", arguments: [number]) ) - obj["hash"] = RPCObject( hash ) - obj["parentHash"] = RPCObject( parentHash ) - obj["nonce"] = RPCObject( nonce.hexValue ) - obj["sha3Uncles"] = RPCObject( sha3Uncles ) - obj["logsBloom"] = RPCObject( logsBloom ) - obj["transactionsRoot"] = RPCObject( transactionsRoot ) - obj["stateRoot"] = RPCObject( stateRoot ) - obj["receiptsRoot"] = RPCObject( receiptsRoot ) - obj["miner"] = RPCObject( miner ) - obj["difficulty"] = RPCObject( difficulty.hexValue ) - obj["totalDifficulty"] = RPCObject( totalDifficulty.hexValue ) - obj["extraData"] = RPCObject( extraData ) - obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) - obj["gasLimit"] = RPCObject( String(format: "0x%1x", arguments: [gasLimit]) ) - obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) - obj["timestamp"] = RPCObject( String(format: "0x%1x", arguments: [timestamp]) ) - obj["uncles"] = RPCObject( uncles ) - return obj - } - - /// initialize the EthBlockdataWithTxHashes - /// - /// - Parameter transactions : Array of transaction hashes - /// - Parameter number : the block number. `null` when its pending block. - /// - Parameter hash : hash of the block. `null` when its pending block. - /// - Parameter parentHash : hash of the parent block. - /// - Parameter nonce : hash of the generated proof-of-work. `null` when its pending block. - /// - Parameter sha3Uncles : SHA3 of the uncles Merkle root in the block. - /// - Parameter logsBloom : the bloom filter for the logs of the block. `null` when its pending block. - /// - Parameter transactionsRoot : the root of the transaction trie of the block. - /// - Parameter stateRoot : the root of the final state trie of the block. - /// - Parameter receiptsRoot : the root of the receipts trie of the block. - /// - Parameter miner : the address of the beneficiary to whom the mining rewards were given. - /// - Parameter difficulty : integer of the difficulty for this block. - /// - Parameter totalDifficulty : integer of the total difficulty of the chain until this block. - /// - Parameter extraData : the "extra data" field of this block. - /// - Parameter size : integer the size of this block in bytes. - /// - Parameter gasLimit : the maximum gas allowed in this block. - /// - Parameter gasUsed : the total used gas by all transactions in this block. - /// - Parameter timestamp : the unix timestamp for when the block was collated. - /// - Parameter uncles : Array of uncle hashes. - public init(transactions: [String], number: UInt64, hash: String, parentHash: String, nonce: UInt256, sha3Uncles: String, logsBloom: String, transactionsRoot: String, stateRoot: String, receiptsRoot: String, miner: String, difficulty: UInt256, totalDifficulty: UInt256, extraData: String, size: UInt64, gasLimit: UInt64, gasUsed: UInt64, timestamp: UInt64, uncles: [String]) { - self.transactions = transactions - self.number = number - self.hash = hash - self.parentHash = parentHash - self.nonce = nonce - self.sha3Uncles = sha3Uncles - self.logsBloom = logsBloom - self.transactionsRoot = transactionsRoot - self.stateRoot = stateRoot - self.receiptsRoot = receiptsRoot - self.miner = miner - self.difficulty = difficulty - self.totalDifficulty = totalDifficulty - self.extraData = extraData - self.size = size - self.gasLimit = gasLimit - self.gasUsed = gasUsed - self.timestamp = timestamp - self.uncles = uncles - } -} - -/// the blockdata, or in case the block with that number does not exist, `null` will be returned. -public struct EthBlockdata { - /// Array of transaction objects - public var transactions: [EthTransactiondata] - - /// the block number. `null` when its pending block. - public var number: UInt64 - - /// hash of the block. `null` when its pending block. - public var hash: String - - /// hash of the parent block. - public var parentHash: String - - /// hash of the generated proof-of-work. `null` when its pending block. - public var nonce: UInt256 - - /// SHA3 of the uncles Merkle root in the block. - public var sha3Uncles: String - - /// the bloom filter for the logs of the block. `null` when its pending block. - public var logsBloom: String - - /// the root of the transaction trie of the block. - public var transactionsRoot: String - - /// the root of the final state trie of the block. - public var stateRoot: String - - /// the root of the receipts trie of the block. - public var receiptsRoot: String - - /// the address of the beneficiary to whom the mining rewards were given. - public var miner: String - - /// integer of the difficulty for this block. - public var difficulty: UInt256 - - /// integer of the total difficulty of the chain until this block. - public var totalDifficulty: UInt256 - - /// the "extra data" field of this block. - public var extraData: String - - /// integer the size of this block in bytes. - public var size: UInt64 - - /// the maximum gas allowed in this block. - public var gasLimit: UInt64 - - /// the total used gas by all transactions in this block. - public var gasUsed: UInt64 - - /// the unix timestamp for when the block was collated. - public var timestamp: UInt64 - - /// Array of uncle hashes. - public var uncles: [String] - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - transactions = try toArray(obj["transactions"])!.map({ try EthTransactiondata($0,false)! }) - number = try toUInt64(obj["number"],false)! - hash = try toString(obj["hash"],false)! - parentHash = try toString(obj["parentHash"],false)! - nonce = try toUInt256(obj["nonce"],false)! - sha3Uncles = try toString(obj["sha3Uncles"],false)! - logsBloom = try toString(obj["logsBloom"],false)! - transactionsRoot = try toString(obj["transactionsRoot"],false)! - stateRoot = try toString(obj["stateRoot"],false)! - receiptsRoot = try toString(obj["receiptsRoot"],false)! - miner = try toString(obj["miner"],false)! - difficulty = try toUInt256(obj["difficulty"],false)! - totalDifficulty = try toUInt256(obj["totalDifficulty"],false)! - extraData = try toString(obj["extraData"],false)! - size = try toUInt64(obj["size"],false)! - gasLimit = try toUInt64(obj["gasLimit"],false)! - gasUsed = try toUInt64(obj["gasUsed"],false)! - timestamp = try toUInt64(obj["timestamp"],false)! - uncles = try toArray(obj["uncles"])!.map({ try toString($0,false)! }) - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["number"] = RPCObject( String(format: "0x%1x", arguments: [number]) ) - obj["hash"] = RPCObject( hash ) - obj["parentHash"] = RPCObject( parentHash ) - obj["nonce"] = RPCObject( nonce.hexValue ) - obj["sha3Uncles"] = RPCObject( sha3Uncles ) - obj["logsBloom"] = RPCObject( logsBloom ) - obj["transactionsRoot"] = RPCObject( transactionsRoot ) - obj["stateRoot"] = RPCObject( stateRoot ) - obj["receiptsRoot"] = RPCObject( receiptsRoot ) - obj["miner"] = RPCObject( miner ) - obj["difficulty"] = RPCObject( difficulty.hexValue ) - obj["totalDifficulty"] = RPCObject( totalDifficulty.hexValue ) - obj["extraData"] = RPCObject( extraData ) - obj["size"] = RPCObject( String(format: "0x%1x", arguments: [size]) ) - obj["gasLimit"] = RPCObject( String(format: "0x%1x", arguments: [gasLimit]) ) - obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) - obj["timestamp"] = RPCObject( String(format: "0x%1x", arguments: [timestamp]) ) - obj["uncles"] = RPCObject( uncles ) - return obj - } - - /// initialize the EthBlockdata - /// - /// - Parameter transactions : Array of transaction objects - /// - Parameter number : the block number. `null` when its pending block. - /// - Parameter hash : hash of the block. `null` when its pending block. - /// - Parameter parentHash : hash of the parent block. - /// - Parameter nonce : hash of the generated proof-of-work. `null` when its pending block. - /// - Parameter sha3Uncles : SHA3 of the uncles Merkle root in the block. - /// - Parameter logsBloom : the bloom filter for the logs of the block. `null` when its pending block. - /// - Parameter transactionsRoot : the root of the transaction trie of the block. - /// - Parameter stateRoot : the root of the final state trie of the block. - /// - Parameter receiptsRoot : the root of the receipts trie of the block. - /// - Parameter miner : the address of the beneficiary to whom the mining rewards were given. - /// - Parameter difficulty : integer of the difficulty for this block. - /// - Parameter totalDifficulty : integer of the total difficulty of the chain until this block. - /// - Parameter extraData : the "extra data" field of this block. - /// - Parameter size : integer the size of this block in bytes. - /// - Parameter gasLimit : the maximum gas allowed in this block. - /// - Parameter gasUsed : the total used gas by all transactions in this block. - /// - Parameter timestamp : the unix timestamp for when the block was collated. - /// - Parameter uncles : Array of uncle hashes. - public init(transactions: [EthTransactiondata], number: UInt64, hash: String, parentHash: String, nonce: UInt256, sha3Uncles: String, logsBloom: String, transactionsRoot: String, stateRoot: String, receiptsRoot: String, miner: String, difficulty: UInt256, totalDifficulty: UInt256, extraData: String, size: UInt64, gasLimit: UInt64, gasUsed: UInt64, timestamp: UInt64, uncles: [String]) { - self.transactions = transactions - self.number = number - self.hash = hash - self.parentHash = parentHash - self.nonce = nonce - self.sha3Uncles = sha3Uncles - self.logsBloom = logsBloom - self.transactionsRoot = transactionsRoot - self.stateRoot = stateRoot - self.receiptsRoot = receiptsRoot - self.miner = miner - self.difficulty = difficulty - self.totalDifficulty = totalDifficulty - self.extraData = extraData - self.size = size - self.gasLimit = gasLimit - self.gasUsed = gasUsed - self.timestamp = timestamp - self.uncles = uncles - } -} - -/// Array of transaction objects -public struct EthTransactiondata { - /// receipient of the transaction. - public var to: String - - /// sender or signer of the transaction - public var from: String - - /// value in wei to send - public var value: UInt256 - - /// the gas to be send along - public var gas: UInt64 - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64 - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64 - - /// blockHash of the block holding this transaction or `null` if still pending. - public var blockHash: String - - /// blockNumber of the block holding this transaction or `null` if still pending. - public var blockNumber: UInt64 - - /// transactionHash - public var hash: String - - /// data of the transaaction - public var input: String - - /// index of the transaaction in the block - public var transactionIndex: UInt64 - - /// recovery-byte of the signature - public var v: String - - /// x-value of the EC-Point of the signature - public var r: String - - /// y-value of the EC-Point of the signature - public var s: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],false)! - from = try toString(obj["from"],false)! - value = try toUInt256(obj["value"],false)! - gas = try toUInt64(obj["gas"],false)! - gasPrice = try toUInt64(obj["gasPrice"],false)! - nonce = try toUInt64(obj["nonce"],false)! - blockHash = try toString(obj["blockHash"],false)! - blockNumber = try toUInt64(obj["blockNumber"],false)! - hash = try toString(obj["hash"],false)! - input = try toString(obj["input"],false)! - transactionIndex = try toUInt64(obj["transactionIndex"],false)! - v = try toString(obj["v"],false)! - r = try toString(obj["r"],false)! - s = try toString(obj["s"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["to"] = RPCObject( to ) - obj["from"] = RPCObject( from ) - obj["value"] = RPCObject( value.hexValue ) - obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [gas]) ) - obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [gasPrice]) ) - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["blockHash"] = RPCObject( blockHash ) - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - obj["hash"] = RPCObject( hash ) - obj["input"] = RPCObject( input ) - obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) - obj["v"] = RPCObject( v ) - obj["r"] = RPCObject( r ) - obj["s"] = RPCObject( s ) - return obj - } - - /// initialize the EthTransactiondata - /// - /// - Parameter to : receipient of the transaction. - /// - Parameter from : sender or signer of the transaction - /// - Parameter value : value in wei to send - /// - Parameter gas : the gas to be send along - /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - /// - Parameter blockHash : blockHash of the block holding this transaction or `null` if still pending. - /// - Parameter blockNumber : blockNumber of the block holding this transaction or `null` if still pending. - /// - Parameter hash : transactionHash - /// - Parameter input : data of the transaaction - /// - Parameter transactionIndex : index of the transaaction in the block - /// - Parameter v : recovery-byte of the signature - /// - Parameter r : x-value of the EC-Point of the signature - /// - Parameter s : y-value of the EC-Point of the signature - public init(to: String, from: String, value: UInt256, gas: UInt64, gasPrice: UInt64, nonce: UInt64, blockHash: String, blockNumber: UInt64, hash: String, input: String, transactionIndex: UInt64, v: String, r: String, s: String) { - self.to = to - self.from = from - self.value = value - self.gas = gas - self.gasPrice = gasPrice - self.nonce = nonce - self.blockHash = blockHash - self.blockNumber = blockNumber - self.hash = hash - self.input = input - self.transactionIndex = transactionIndex - self.v = v - self.r = r - self.s = s - } -} - -/// The filter criteria for the events. -public struct EthFilter { - /// Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - public var fromBlock: UInt64? - - /// Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - public var toBlock: UInt64? - - /// Contract address or a list of addresses from which logs should originate. - public var address: String? - - /// Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. - public var topics: [String?]? - - /// With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. - public var blockhash: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - fromBlock = try toUInt64(obj["fromBlock"],true)! - toBlock = try toUInt64(obj["toBlock"],true)! - address = try toString(obj["address"],true)! - if let topics = try toArray(obj["topics"],true) { - self.topics = try topics.map({ try toString($0,true) }) - } else { - self.topics = nil - } - blockhash = try toString(obj["blockhash"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - if let x = fromBlock { obj["fromBlock"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = toBlock { obj["toBlock"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = address { obj["address"] = RPCObject( x ) } - if let x = topics { obj["topics"] = RPCObject( x ) } - if let x = blockhash { obj["blockhash"] = RPCObject( x ) } - return obj - } - - /// initialize the EthFilter - /// - /// - Parameter fromBlock : Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - /// - Parameter toBlock : Integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions. - /// - Parameter address : Contract address or a list of addresses from which logs should originate. - /// - Parameter topics : Array of 32 Bytes DATA topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options. - /// - Parameter blockhash : With the addition of EIP-234, blockHash will be a new filter option which restricts the logs returned to the single block with the 32-byte hash blockHash. Using blockHash is equivalent to fromBlock = toBlock = the block number with hash blockHash. If blockHash is present in in the filter criteria, then neither fromBlock nor toBlock are allowed. - public init(fromBlock: UInt64? = nil, toBlock: UInt64? = nil, address: String? = nil, topics: [String?]? = nil, blockhash: String? = nil) { - self.fromBlock = fromBlock - self.toBlock = toBlock - self.address = address - self.topics = topics - self.blockhash = blockhash - } -} - -/// array with all found event matching the specified filter -public struct Ethlog { - /// the address triggering the event. - public var address: String - - /// the blockNumber - public var blockNumber: UInt64 - - /// blockhash if ther containing block - public var blockHash: String - - /// abi-encoded data of the event (all non indexed fields) - public var data: String - - /// the index of the even within the block. - public var logIndex: Int - - /// the reorg-status of the event. - public var removed: Bool - - /// array of 32byte-topics of the indexed fields. - public var topics: [String] - - /// requested transactionHash - public var transactionHash: String - - /// transactionIndex within the containing block. - public var transactionIndex: Int - - /// index of the event within the transaction. - public var transactionLogIndex: Int? - - /// mining-status - public var type: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - address = try toString(obj["address"],false)! - blockNumber = try toUInt64(obj["blockNumber"],false)! - blockHash = try toString(obj["blockHash"],false)! - data = try toString(obj["data"],false)! - logIndex = try toInt(obj["logIndex"],false)! - removed = try toBool(obj["removed"],false)! - topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) - transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toInt(obj["transactionIndex"],false)! - transactionLogIndex = try toInt(obj["transactionLogIndex"],true)! - type = try toString(obj["type"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject( address ) - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - obj["blockHash"] = RPCObject( blockHash ) - obj["data"] = RPCObject( data ) - obj["logIndex"] = RPCObject( String(format: "0x%1x", arguments: [logIndex]) ) - obj["removed"] = RPCObject( removed ) - obj["topics"] = RPCObject( topics ) - obj["transactionHash"] = RPCObject( transactionHash ) - obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) - if let x = transactionLogIndex { obj["transactionLogIndex"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = type { obj["type"] = RPCObject( x ) } - return obj - } - - /// initialize the Ethlog - /// - /// - Parameter address : the address triggering the event. - /// - Parameter blockNumber : the blockNumber - /// - Parameter blockHash : blockhash if ther containing block - /// - Parameter data : abi-encoded data of the event (all non indexed fields) - /// - Parameter logIndex : the index of the even within the block. - /// - Parameter removed : the reorg-status of the event. - /// - Parameter topics : array of 32byte-topics of the indexed fields. - /// - Parameter transactionHash : requested transactionHash - /// - Parameter transactionIndex : transactionIndex within the containing block. - /// - Parameter transactionLogIndex : index of the event within the transaction. - /// - Parameter type : mining-status - public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int? = nil, type: String? = nil) { - self.address = address - self.blockNumber = blockNumber - self.blockHash = blockHash - self.data = data - self.logIndex = logIndex - self.removed = removed - self.topics = topics - self.transactionHash = transactionHash - self.transactionIndex = transactionIndex - self.transactionLogIndex = transactionLogIndex - self.type = type - } -} - -/// the transactiondata to send -public struct EthTransaction { - /// receipient of the transaction. - public var to: String? - - /// sender of the address (if not sepcified, the first signer will be the sender) - public var from: String? - - /// value in wei to send - public var value: UInt256? - - /// the gas to be send along - public var gas: UInt64? - - /// the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - public var gasPrice: UInt64? - - /// the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - public var nonce: UInt64? - - /// the data-section of the transaction - public var data: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - to = try toString(obj["to"],true)! - from = try toString(obj["from"],true)! - value = try toUInt256(obj["value"],true)! - gas = try toUInt64(obj["gas"],true)! - gasPrice = try toUInt64(obj["gasPrice"],true)! - nonce = try toUInt64(obj["nonce"],true)! - data = try toString(obj["data"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - if let x = to { obj["to"] = RPCObject( x ) } - if let x = from { obj["from"] = RPCObject( x ) } - if let x = value { obj["value"] = RPCObject( x.hexValue ) } - if let x = gas { obj["gas"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = gasPrice { obj["gasPrice"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = nonce { obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = data { obj["data"] = RPCObject( x ) } - return obj - } - - /// initialize the EthTransaction - /// - /// - Parameter to : receipient of the transaction. - /// - Parameter from : sender of the address (if not sepcified, the first signer will be the sender) - /// - Parameter value : value in wei to send - /// - Parameter gas : the gas to be send along - /// - Parameter gasPrice : the price in wei for one gas-unit. If not specified it will be fetched using `eth_gasPrice` - /// - Parameter nonce : the current nonce of the sender. If not specified it will be fetched using `eth_getTransactionCount` - /// - Parameter data : the data-section of the transaction - public init(to: String? = nil, from: String? = nil, value: UInt256? = nil, gas: UInt64? = nil, gasPrice: UInt64? = nil, nonce: UInt64? = nil, data: String? = nil) { - self.to = to - self.from = from - self.value = value - self.gas = gas - self.gasPrice = gasPrice - self.nonce = nonce - self.data = data - } -} - -/// the transactionReceipt -public struct EthTransactionReceipt { - /// the blockNumber - public var blockNumber: UInt64 - - /// blockhash if ther containing block - public var blockHash: String - - /// the deployed contract in case the tx did deploy a new contract - public var contractAddress: String? - - /// gas used for all transaction up to this one in the block - public var cumulativeGasUsed: UInt64 - - /// gas used by this transaction. - public var gasUsed: UInt64 - - /// array of events created during execution of the tx - public var logs: [Ethlog] - - /// bloomfilter used to detect events for `eth_getLogs` - public var logsBloom: String - - /// error-status of the tx. 0x1 = success 0x0 = failure - public var status: Int - - /// requested transactionHash - public var transactionHash: String - - /// transactionIndex within the containing block. - public var transactionIndex: Int - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockNumber = try toUInt64(obj["blockNumber"],false)! - blockHash = try toString(obj["blockHash"],false)! - contractAddress = try toString(obj["contractAddress"],true)! - cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! - gasUsed = try toUInt64(obj["gasUsed"],false)! - logs = try toArray(obj["logs"])!.map({ try Ethlog($0,false)! }) - logsBloom = try toString(obj["logsBloom"],false)! - status = try toInt(obj["status"],false)! - transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toInt(obj["transactionIndex"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - obj["blockHash"] = RPCObject( blockHash ) - if let x = contractAddress { obj["contractAddress"] = RPCObject( x ) } - obj["cumulativeGasUsed"] = RPCObject( String(format: "0x%1x", arguments: [cumulativeGasUsed]) ) - obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) - obj["logsBloom"] = RPCObject( logsBloom ) - obj["status"] = RPCObject( String(format: "0x%1x", arguments: [status]) ) - obj["transactionHash"] = RPCObject( transactionHash ) - obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) - return obj - } - - /// initialize the EthTransactionReceipt - /// - /// - Parameter blockNumber : the blockNumber - /// - Parameter blockHash : blockhash if ther containing block - /// - Parameter contractAddress : the deployed contract in case the tx did deploy a new contract - /// - Parameter cumulativeGasUsed : gas used for all transaction up to this one in the block - /// - Parameter gasUsed : gas used by this transaction. - /// - Parameter logs : array of events created during execution of the tx - /// - Parameter logsBloom : bloomfilter used to detect events for `eth_getLogs` - /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure - /// - Parameter transactionHash : requested transactionHash - /// - Parameter transactionIndex : transactionIndex within the containing block. - public init(blockNumber: UInt64, blockHash: String, contractAddress: String? = nil, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: [Ethlog], logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { - self.blockNumber = blockNumber - self.blockHash = blockHash - self.contractAddress = contractAddress - self.cumulativeGasUsed = cumulativeGasUsed - self.gasUsed = gasUsed - self.logs = logs - self.logsBloom = logsBloom - self.status = status - self.transactionHash = transactionHash - self.transactionIndex = transactionIndex - } -} \ No newline at end of file diff --git a/swift/Sources/In3/API/Ipfs.swift b/swift/Sources/In3/API/Ipfs.swift deleted file mode 100644 index 7911e3c72..000000000 --- a/swift/Sources/In3/API/Ipfs.swift +++ /dev/null @@ -1,70 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// A Node supporting IPFS must support these 2 RPC-Methods for uploading and downloading IPFS-Content. The node itself will run a ipfs-client to handle them. -/// -/// Fetching ipfs-content can be easily verified by creating the ipfs-hash based on the received data and comparing it to the requested ipfs-hash. Since there is no chance of manipulating the data, there is also no need to put a deposit or convict a node. That's why the registry-contract allows a zero-deposit fot ipfs-nodes. -/// -public class Ipfs { - internal var in3: In3 - - /// initialiazes the Ipfs API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// Fetches the data for a requested ipfs-hash. If the node is not able to resolve the hash or find the data a error should be reported. - /// - Parameter ipfshash : the ipfs multi hash - /// - Parameter encoding : the encoding used for the response. ( `hex` , `base64` or `utf8`) - /// - Returns: the content matching the requested hash encoded in the defined encoding. - /// - /// **Example** - /// - /// ```swift - /// Ipfs(in3).get(ipfshash: "QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD", encoding: "utf8") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = I love Incubed - /// } - /// } - /// - /// ``` - /// - public func get(ipfshash: String, encoding: String) -> Future { - return execAndConvert(in3: in3, method: "ipfs_get", params:RPCObject( ipfshash), RPCObject( encoding), convertWith: toString ) - } - - /// Stores ipfs-content to the ipfs network. - /// Important! As a client there is no garuantee that a node made this content available. ( just like `eth_sendRawTransaction` will only broadcast it). - /// Even if the node stores the content there is no gurantee it will do it forever. - /// - /// - Parameter data : the content encoded with the specified encoding. - /// - Parameter encoding : the encoding used for the request. ( `hex` , `base64` or `utf8`) - /// - Returns: the ipfs multi hash - /// - /// **Example** - /// - /// ```swift - /// Ipfs(in3).put(data: "I love Incubed", encoding: "utf8") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = QmSepGsypERjq71BSm4Cjq7j8tyAUnCw6ZDTeNdE8RUssD - /// } - /// } - /// - /// ``` - /// - public func put(data: String, encoding: String) -> Future { - return execAndConvert(in3: in3, method: "ipfs_put", params:RPCObject( data), RPCObject( encoding), convertWith: toString ) - } - - -} diff --git a/swift/Sources/In3/API/Nodelist.swift b/swift/Sources/In3/API/Nodelist.swift deleted file mode 100644 index 81796ff22..000000000 --- a/swift/Sources/In3/API/Nodelist.swift +++ /dev/null @@ -1,408 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// special Incubed nodelist-handling functions. Most of those are only used internally. -public class Nodelist { - internal var in3: In3 - - /// initialiazes the Nodelist API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// fetches and verifies the nodeList from a node - /// - Parameter limit : if the number is defined and >0 this method will return a partial nodeList limited to the given number. - /// - Parameter seed : this 32byte hex integer is used to calculate the indexes of the partial nodeList. It is expected to be a random value choosen by the client in order to make the result deterministic. - /// - Parameter addresses : a optional array of addresses of signers the nodeList must include. - /// - Returns: the current nodelist - /// - /// **Example** - /// - /// ```swift - /// Nodelist(in3).nodes(limit: 2, seed: "0xe9c15c3b26342e3287bb069e433de48ac3fa4ddd32a31b48e426d19d761d7e9b", addresses: []) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // totalServers: 5 - /// // contract: "0x64abe24afbba64cae47e3dc3ced0fcab95e4edd5" - /// // registryId: "0x423dd84f33a44f60e5d58090dcdcc1c047f57be895415822f211b8cd1fd692e3" - /// // lastBlockNumber: 8669495 - /// // nodes: - /// // - url: https://in3-v2.slock.it/mainnet/nd-3 - /// // address: "0x945F75c0408C0026a3CD204d36f5e47745182fd4" - /// // index: 2 - /// // deposit: "10000000000000000" - /// // props: 29 - /// // timeout: 3600 - /// // registerTime: 1570109570 - /// // weight: 2000 - /// // proofHash: "0x27ffb9b7dc2c5f800c13731e7c1e43fb438928dd5d69aaa8159c21fb13180a4c" - /// // - url: https://in3-v2.slock.it/mainnet/nd-5 - /// // address: "0xbcdF4E3e90cc7288b578329efd7bcC90655148d2" - /// // index: 4 - /// // deposit: "10000000000000000" - /// // props: 29 - /// // timeout: 3600 - /// // registerTime: 1570109690 - /// // weight: 2000 - /// // proofHash: "0xd0dbb6f1e28a8b90761b973e678cf8ecd6b5b3a9d61fb9797d187be011ee9ec7" - /// } - /// } - /// - /// ``` - /// - public func nodes(limit: Int? = nil, seed: String? = nil, addresses: [String]? = nil) -> Future { - return execAndConvert(in3: in3, method: "in3_nodeList", params:limit == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", limit!) ), seed == nil ? RPCObject.none : RPCObject( seed! ), addresses == nil ? RPCObject.none : RPCObject( addresses! ), convertWith: { try NodeListDefinition($0,$1) } ) - } - - /// requests a signed blockhash from the node. - /// In most cases these requests will come from other nodes, because the client simply adds the addresses of the requested signers - /// and the processising nodes will then aquire the signatures with this method from the other nodes. - /// - /// Since each node has a risk of signing a wrong blockhash and getting convicted and losing its deposit, - /// per default nodes will and should not sign blockHash of the last `minBlockHeight` (default: 6) blocks! - /// - /// - Parameter blocks : array of requested blocks. - /// - Returns: the Array with signatures of all the requires blocks. - /// - /// **Example** - /// - /// ```swift - /// Nodelist(in3).signBlockHash(blocks: NodelistBlocks(blockNumber: 8770580)) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // - blockHash: "0xd8189793f64567992eaadefc51834f3d787b03e9a6850b8b9b8003d8d84a76c8" - /// // block: 8770580 - /// // r: "0x954ed45416e97387a55b2231bff5dd72e822e4a5d60fa43bc9f9e49402019337" - /// // s: "0x277163f586585092d146d0d6885095c35c02b360e4125730c52332cf6b99e596" - /// // v: 28 - /// // msgHash: "0x40c23a32947f40a2560fcb633ab7fa4f3a96e33653096b17ec613fbf41f946ef" - /// } - /// } - /// - /// ``` - /// - public func signBlockHash(blocks: NodelistBlocks) -> Future { - return execAndConvert(in3: in3, method: "in3_sign", params:RPCObject( blocks.toRPCDict()), convertWith: { try NodelistSignBlockHash($0,$1) } ) - } - - /// Returns whitelisted in3-nodes addresses. The whitelist addressed are accquired from whitelist contract that user can specify in request params. - /// - Parameter address : address of whitelist contract - /// - Returns: the whitelisted addresses - /// - /// **Example** - /// - /// ```swift - /// Nodelist(in3).whitelist(address: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // totalServers: 2 - /// // contract: "0x08e97ef0a92EB502a1D7574913E2a6636BeC557b" - /// // lastBlockNumber: 1546354 - /// // nodes: - /// // - "0x1fe2e9bf29aa1938859af64c413361227d04059a" - /// // - "0x45d45e6ff99e6c34a235d263965910298985fcfe" - /// } - /// } - /// - /// ``` - /// - public func whitelist(address: String) -> Future { - return execAndConvert(in3: in3, method: "in3_whitelist", params:RPCObject( address), convertWith: { try NodelistWhitelist($0,$1) } ) - } - - -} -/// the current nodelist -public struct NodeListDefinition { - /// a array of node definitions. - public var nodes: [Node] - - /// the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. - public var contract: String - - /// the registryId (32 bytes) of the contract, which is there to verify the correct contract. - public var registryId: String - - /// the blockNumber of the last change of the list (usually the last event). - public var lastBlockNumber: UInt64 - - /// the total numbers of nodes. - public var totalServer: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - nodes = try toArray(obj["nodes"])!.map({ try Node($0,false)! }) - contract = try toString(obj["contract"],false)! - registryId = try toString(obj["registryId"],false)! - lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! - totalServer = try toUInt64(obj["totalServer"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["contract"] = RPCObject( contract ) - obj["registryId"] = RPCObject( registryId ) - obj["lastBlockNumber"] = RPCObject( String(format: "0x%1x", arguments: [lastBlockNumber]) ) - obj["totalServer"] = RPCObject( String(format: "0x%1x", arguments: [totalServer]) ) - return obj - } - - /// initialize the NodeListDefinition - /// - /// - Parameter nodes : a array of node definitions. - /// - Parameter contract : the address of the Incubed-storage-contract. The client may use this information to verify that we are talking about the same contract or throw an exception otherwise. - /// - Parameter registryId : the registryId (32 bytes) of the contract, which is there to verify the correct contract. - /// - Parameter lastBlockNumber : the blockNumber of the last change of the list (usually the last event). - /// - Parameter totalServer : the total numbers of nodes. - public init(nodes: [Node], contract: String, registryId: String, lastBlockNumber: UInt64, totalServer: UInt64) { - self.nodes = nodes - self.contract = contract - self.registryId = registryId - self.lastBlockNumber = lastBlockNumber - self.totalServer = totalServer - } -} - -/// a array of node definitions. -public struct Node { - /// the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. - public var url: String - - /// the address of the signer - public var address: String - - /// the index within the nodeList of the contract - public var index: UInt64 - - /// the stored deposit - public var deposit: UInt256 - - /// the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - public var props: String - - /// the time in seconds describing how long the deposit would be locked when trying to unregister a node. - public var timeout: UInt64 - - /// unix timestamp in seconds when the node has registered. - public var registerTime: UInt64 - - /// the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. - public var weight: UInt64 - - /// a hash value containing the above values. - /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof - /// per node instead of verifying each property as its own storage value. - /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` - /// - public var proofHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - url = try toString(obj["url"],false)! - address = try toString(obj["address"],false)! - index = try toUInt64(obj["index"],false)! - deposit = try toUInt256(obj["deposit"],false)! - props = try toString(obj["props"],false)! - timeout = try toUInt64(obj["timeout"],false)! - registerTime = try toUInt64(obj["registerTime"],false)! - weight = try toUInt64(obj["weight"],false)! - proofHash = try toString(obj["proofHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["url"] = RPCObject( url ) - obj["address"] = RPCObject( address ) - obj["index"] = RPCObject( String(format: "0x%1x", arguments: [index]) ) - obj["deposit"] = RPCObject( deposit.hexValue ) - obj["props"] = RPCObject( props ) - obj["timeout"] = RPCObject( String(format: "0x%1x", arguments: [timeout]) ) - obj["registerTime"] = RPCObject( String(format: "0x%1x", arguments: [registerTime]) ) - obj["weight"] = RPCObject( String(format: "0x%1x", arguments: [weight]) ) - obj["proofHash"] = RPCObject( proofHash ) - return obj - } - - /// initialize the Node - /// - /// - Parameter url : the url of the node. Currently only http/https is supported, but in the future this may even support onion-routing or any other protocols. - /// - Parameter address : the address of the signer - /// - Parameter index : the index within the nodeList of the contract - /// - Parameter deposit : the stored deposit - /// - Parameter props : the bitset of capabilities as described in the [Node Structure](spec.html#node-structure) - /// - Parameter timeout : the time in seconds describing how long the deposit would be locked when trying to unregister a node. - /// - Parameter registerTime : unix timestamp in seconds when the node has registered. - /// - Parameter weight : the weight of a node ( not used yet ) describing the amount of request-points it can handle per second. - /// - Parameter proofHash : a hash value containing the above values. - /// This hash is explicitly stored in the contract, which enables the client to have only one merkle proof - /// per node instead of verifying each property as its own storage value. - /// The proof hash is build `keccak256( abi.encodePacked( deposit, timeout, registerTime, props, signer, url ))` - /// - public init(url: String, address: String, index: UInt64, deposit: UInt256, props: String, timeout: UInt64, registerTime: UInt64, weight: UInt64, proofHash: String) { - self.url = url - self.address = address - self.index = index - self.deposit = deposit - self.props = props - self.timeout = timeout - self.registerTime = registerTime - self.weight = weight - self.proofHash = proofHash - } -} - -/// array of requested blocks. -public struct NodelistBlocks { - /// the blockNumber to sign - public var blockNumber: UInt64 - - /// the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. - public var hash: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockNumber = try toUInt64(obj["blockNumber"],false)! - hash = try toString(obj["hash"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - if let x = hash { obj["hash"] = RPCObject( x ) } - return obj - } - - /// initialize the NodelistBlocks - /// - /// - Parameter blockNumber : the blockNumber to sign - /// - Parameter hash : the expected hash. This is optional and can be used to check if the expected hash is correct, but as a client you should not rely on it, but only on the hash in the signature. - public init(blockNumber: UInt64, hash: String? = nil) { - self.blockNumber = blockNumber - self.hash = hash - } -} - -/// the Array with signatures of all the requires blocks. -public struct NodelistSignBlockHash { - /// the blockhash which was signed. - public var blockHash: String - - /// the blocknumber - public var block: UInt64 - - /// r-value of the signature - public var r: String - - /// s-value of the signature - public var s: String - - /// v-value of the signature - public var v: String - - /// the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` - public var msgHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockHash = try toString(obj["blockHash"],false)! - block = try toUInt64(obj["block"],false)! - r = try toString(obj["r"],false)! - s = try toString(obj["s"],false)! - v = try toString(obj["v"],false)! - msgHash = try toString(obj["msgHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockHash"] = RPCObject( blockHash ) - obj["block"] = RPCObject( String(format: "0x%1x", arguments: [block]) ) - obj["r"] = RPCObject( r ) - obj["s"] = RPCObject( s ) - obj["v"] = RPCObject( v ) - obj["msgHash"] = RPCObject( msgHash ) - return obj - } - - /// initialize the NodelistSignBlockHash - /// - /// - Parameter blockHash : the blockhash which was signed. - /// - Parameter block : the blocknumber - /// - Parameter r : r-value of the signature - /// - Parameter s : s-value of the signature - /// - Parameter v : v-value of the signature - /// - Parameter msgHash : the msgHash signed. This Hash is created with `keccak256( abi.encodePacked( _blockhash, _blockNumber, registryId ))` - public init(blockHash: String, block: UInt64, r: String, s: String, v: String, msgHash: String) { - self.blockHash = blockHash - self.block = block - self.r = r - self.s = s - self.v = v - self.msgHash = msgHash - } -} - -/// the whitelisted addresses -public struct NodelistWhitelist { - /// array of whitelisted nodes addresses. - public var nodes: String - - /// the blockNumber of the last change of the in3 white list event. - public var lastWhiteList: UInt64 - - /// whitelist contract address. - public var contract: String - - /// the blockNumber of the last change of the list (usually the last event). - public var lastBlockNumber: UInt64 - - /// the total numbers of whitelist nodes. - public var totalServer: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - nodes = try toString(obj["nodes"],false)! - lastWhiteList = try toUInt64(obj["lastWhiteList"],false)! - contract = try toString(obj["contract"],false)! - lastBlockNumber = try toUInt64(obj["lastBlockNumber"],false)! - totalServer = try toUInt64(obj["totalServer"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["nodes"] = RPCObject( nodes ) - obj["lastWhiteList"] = RPCObject( String(format: "0x%1x", arguments: [lastWhiteList]) ) - obj["contract"] = RPCObject( contract ) - obj["lastBlockNumber"] = RPCObject( String(format: "0x%1x", arguments: [lastBlockNumber]) ) - obj["totalServer"] = RPCObject( String(format: "0x%1x", arguments: [totalServer]) ) - return obj - } - - /// initialize the NodelistWhitelist - /// - /// - Parameter nodes : array of whitelisted nodes addresses. - /// - Parameter lastWhiteList : the blockNumber of the last change of the in3 white list event. - /// - Parameter contract : whitelist contract address. - /// - Parameter lastBlockNumber : the blockNumber of the last change of the list (usually the last event). - /// - Parameter totalServer : the total numbers of whitelist nodes. - public init(nodes: String, lastWhiteList: UInt64, contract: String, lastBlockNumber: UInt64, totalServer: UInt64) { - self.nodes = nodes - self.lastWhiteList = lastWhiteList - self.contract = contract - self.lastBlockNumber = lastBlockNumber - self.totalServer = totalServer - } -} \ No newline at end of file diff --git a/swift/Sources/In3/API/Utils.swift b/swift/Sources/In3/API/Utils.swift deleted file mode 100644 index c39f21573..000000000 --- a/swift/Sources/In3/API/Utils.swift +++ /dev/null @@ -1,209 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// a Collection of utility-function. -/// -public class Utils { - internal var in3: In3 - - /// initialiazes the Utils API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the value given and returns it as hexstring. - /// - Parameter signature : the signature of the function. e.g. `getBalance(uint256)`. The format is the same as used by solidity to create the functionhash. optional you can also add the return type, which in this case is ignored. - /// - Parameter params : a array of arguments. the number of arguments must match the arguments in the signature. - /// - Returns: the ABI-encoded data as hex including the 4 byte function-signature. These data can be used for `eth_call` or to send a transaction. - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).abiEncode(signature: "getBalance(address)", params: ["0x1234567890123456789012345678901234567890"]) - /// // result = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890" - /// ``` - /// - public func abiEncode(signature: String, params: [AnyObject]) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_abiEncode", params:RPCObject( signature), RPCObject( params), convertWith: toString ) - } - - /// based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function decodes the bytes given and returns it as array of values. - /// - Parameter signature : the signature of the function. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`. If the complete functionhash is given, only the return-part will be used. - /// - Parameter data : the data to decode (usually the result of a eth_call) - /// - Parameter topics : in case of an even the topics (concatinated to max 4x32bytes). This is used if indexed.arguments are used. - /// - Returns: a array with the values after decodeing. - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).abiDecode(signature: "(address,uint256)", data: "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005") - /// // result = - /// // - "0x1234567890123456789012345678901234567890" - /// // - "0x05" - /// ``` - /// - public func abiDecode(signature: String, data: String, topics: String? = nil) throws -> [RPCObject] { - return try execLocalAndConvert(in3: in3, method: "in3_abiDecode", params:RPCObject( signature), RPCObject( data), topics == nil ? RPCObject.none : RPCObject( topics! ), convertWith: { try toArray($0,$1)! } ) - } - - /// Will convert an upper or lowercase Ethereum address to a checksum address. (See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md) ) - /// - Parameter address : the address to convert. - /// - Parameter useChainId : if true, the chainId is integrated as well (See [EIP1191](https://github.com/ethereum/EIPs/issues/1121) ) - /// - Returns: the address-string using the upper/lowercase hex characters. - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).checksumAddress(address: "0x1fe2e9bf29aa1938859af64c413361227d04059a", useChainId: false) - /// // result = "0x1Fe2E9bf29aa1938859Af64C413361227d04059a" - /// ``` - /// - public func checksumAddress(address: String, useChainId: Bool? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_checksumAddress", params:RPCObject( address), useChainId == nil ? RPCObject.none : RPCObject( useChainId! ), convertWith: toString ) - } - - /// converts the given value into wei. - /// - Parameter value : the value, which may be floating number as string - /// - Parameter unit : the unit of the value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` - /// - Returns: the value in wei as hex. - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).toWei(value: "20.0009123", unit: "eth") - /// // result = "0x01159183c4793db800" - /// ``` - /// - public func toWei(value: String, unit: String? = "eth") throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_toWei", params:RPCObject( value), unit == nil ? RPCObject.none : RPCObject( unit! ), convertWith: toString ) - } - - /// converts a given uint (also as hex) with a wei-value into a specified unit. - /// - Parameter value : the value in wei - /// - Parameter unit : the unit of the target value, which must be one of `wei`, `kwei`, `Kwei`, `babbage`, `femtoether`, `mwei`, `Mwei`, `lovelace`, `picoether`, `gwei`, `Gwei`, `shannon`, `nanoether`, `nano`, `szabo`, `microether`, `micro`, `finney`, `milliether`, `milli`, `ether`, `eth`, `kether`, `grand`, `mether`, `gether` or `tether` - /// - Parameter digits : fix number of digits after the comma. If left out, only as many as needed will be included. - /// - Returns: the value as string. - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).fromWei(value: "0x234324abadefdef", unit: "eth", digits: 3) - /// // result = "0.158" - /// ``` - /// - public func fromWei(value: UInt256, unit: String, digits: Int? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_fromWei", params:RPCObject( value), RPCObject( unit), digits == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", digits!) ), convertWith: toString ) - } - - /// clears the incubed cache (usually found in the .in3-folder) - /// - Returns: true indicating the success - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).cacheClear() - /// // result = true - /// ``` - /// - public func cacheClear() throws -> String { - return try execLocalAndConvert(in3: in3, method: "in3_cacheClear", convertWith: toString ) - } - - /// Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. - /// - Returns: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. - public func clientVersion() -> Future { - return execAndConvert(in3: in3, method: "web3_clientVersion", convertWith: toString ) - } - - /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. - /// - /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).keccak(data: "0x1234567890") - /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - /// ``` - /// - public func keccak(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "keccak", params:RPCObject( data), convertWith: toString ) - } - - /// Returns Keccak-256 (not the standardized SHA3-256) of the given data. - /// - /// See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).sha3(data: "0x1234567890") - /// // result = "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - /// ``` - /// - public func sha3(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "web3_sha3", params:RPCObject( data), convertWith: toString ) - } - - /// Returns sha-256 of the given data. - /// - /// No proof needed, since the client will execute this locally. - /// - /// - Parameter data : data to hash - /// - Returns: the 32byte hash of the data - /// - /// **Example** - /// - /// ```swift - /// let result = try Utils(in3).sha256(data: "0x1234567890") - /// // result = "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - /// ``` - /// - public func sha256(data: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "sha256", params:RPCObject( data), convertWith: toString ) - } - - /// calculates the address of a contract about to deploy. The address depends on the senders nonce. - /// - Parameter sender : the sender of the transaction - /// - Parameter nonce : the nonce of the sender during deployment - /// - Returns: the address of the deployed contract - /// - /// **Example** - /// - /// ```swift - /// Utils(in3).calcDeployAddress(sender: "0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c", nonce: 6054986) .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xba866e7bd2573be3eaf5077b557751bb6d58076e" - /// } - /// } - /// - /// ``` - /// - public func calcDeployAddress(sender: String, nonce: UInt64? = nil) -> Future { - return execAndConvert(in3: in3, method: "in3_calcDeployAddress", params:RPCObject( sender), nonce == nil ? RPCObject.none : RPCObject( String(format: "0x%1x", nonce!) ), convertWith: toString ) - } - - /// the Network Version (currently 1) - /// - Returns: the Version number - public func version() throws -> String { - return try execLocalAndConvert(in3: in3, method: "net_version", convertWith: toString ) - } - - -} diff --git a/swift/Sources/In3/API/Zksync.swift b/swift/Sources/In3/API/Zksync.swift deleted file mode 100644 index 283668bfa..000000000 --- a/swift/Sources/In3/API/Zksync.swift +++ /dev/null @@ -1,1011 +0,0 @@ -/// this is generated file don't edit it manually! - -import Foundation - -/// *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* -/// -/// the zksync-plugin is able to handle operations to use [zksync](https://zksync.io/) like deposit transfer or withdraw. Also see the #in3-config on how to configure the zksync-server or account. -/// -/// Also in order to sign messages you need to set a signer! -/// -/// All zksync-methods can be used with `zksync_` or `zk_` prefix. -/// -public class Zksync { - internal var in3: In3 - - /// initialiazes the Zksync API - /// - Parameter in3 : the incubed Client - init(_ in3: In3) { - self.in3 = in3 - } - - /// returns the contract address - /// - Returns: fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).contractAddress() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // govContract: "0x34460C0EB5074C29A9F6FE13b8e7E23A0D08aF01" - /// // mainContract: "0xaBEA9132b05A70803a4E85094fD0e1800777fBEF" - /// } - /// } - /// - /// ``` - /// - public func contractAddress() -> Future { - return execAndConvert(in3: in3, method: "zksync_contract_address", convertWith: { try ZksyncContractAddress($0,$1) } ) - } - - /// returns the list of all available tokens - /// - Returns: a array of tokens-definitions. This request also caches them and will return the results from cahe if available. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).tokens() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // BAT: - /// // address: "0x0d8775f648430679a709e98d2b0cb6250d2887ef" - /// // decimals: 18 - /// // id: 8 - /// // symbol: BAT - /// // BUSD: - /// // address: "0x4fabb145d64652a948d72533023f6e7a623c7c53" - /// // decimals: 18 - /// // id: 6 - /// // symbol: BUSD - /// // DAI: - /// // address: "0x6b175474e89094c44da98b954eedeac495271d0f" - /// // decimals: 18 - /// // id: 1 - /// // symbol: DAI - /// // ETH: - /// // address: "0x0000000000000000000000000000000000000000" - /// // decimals: 18 - /// // id: 0 - /// // symbol: ETH - /// } - /// } - /// - /// ``` - /// - public func tokens() -> Future<[String:ZksyncTokens]> { - return execAndConvert(in3: in3, method: "zksync_tokens", convertWith: { try toObject($0,$1)!.mapValues({ try ZksyncTokens($0,false)! }) } ) - } - - /// returns account_info from the server - /// - Parameter address : the account-address. if not specified, the client will try to use its own address based on the signer config. - /// - Returns: the current state of the requested account. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).accountInfo() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // address: "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" - /// // committed: - /// // balances: {} - /// // nonce: 0 - /// // pubKeyHash: sync:0000000000000000000000000000000000000000 - /// // depositing: - /// // balances: {} - /// // id: null - /// // verified: - /// // balances: {} - /// // nonce: 0 - /// // pubKeyHash: sync:0000000000000000000000000000000000000000 - /// } - /// } - /// - /// ``` - /// - public func accountInfo(address: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_account_info", params:address == nil ? RPCObject.none : RPCObject( address! ), convertWith: { try ZksyncAccountInfo($0,$1) } ) - } - - /// returns the state or receipt of the the zksync-tx - /// - Parameter tx : the txHash of the send tx - /// - Returns: the current state of the requested tx. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).txInfo(tx: "sync-tx:e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // block: null - /// // executed: false - /// // failReason: null - /// // success: null - /// } - /// } - /// - /// ``` - /// - public func txInfo(tx: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_tx_info", params:RPCObject( tx), convertWith: { try ZksyncTxInfo($0,$1) } ) - } - - /// sets the signerkey based on the current pk or as configured in the config. - /// You can specify the key by either - /// - setting a signer ( the sync key will be derrived through a signature ) - /// - setting the seed directly ( `sync_key` in the config) - /// - setting the `musig_pub_keys` to generate the pubKeyHash based on them - /// - setting the `create2` options and the sync-key will generate the account based on the pubKeyHash - /// - /// - /// we support 3 different signer types (`signer_type` in the `zksync` config) : - /// - /// 1. `pk` - Simple Private Key - /// If a signer is set (for example by setting the pk), incubed will derrive the sync-key through a signature and use it - /// 2. `contract` - Contract Signature - /// In this case a preAuth-tx will be send on L1 using the signer. If this contract is a mutisig, you should make sure, you have set the account explicitly in the config and also activate the multisig-plugin, so the transaction will be send through the multisig. - /// 3. `create2` - Create2 based Contract - /// - /// - Parameter token : the token to pay the gas (either the symbol or the address) - /// - Returns: the pubKeyHash, if it was executed successfully - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).setKey(token: "eth") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = sync:e41d2489571d322189246dafa5ebde1f4699f498 - /// } - /// } - /// - /// ``` - /// - public func setKey(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_set_key", params:RPCObject( token), convertWith: toString ) - } - - /// returns the current PubKeyHash based on the configuration set. - /// - Parameter pubKey : the packed public key to hash ( if given the hash is build based on the given hash, otherwise the hash is based on the config) - /// - Returns: the pubKeyHash - /// - /// **Example** - /// - /// ```swift - /// let result = try Zksync(in3).pubkeyhash() - /// // result = sync:4dcd9bb4463121470c7232efb9ff23ec21398e58 - /// ``` - /// - public func pubkeyhash(pubKey: String? = nil) throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_pubkeyhash", params:pubKey == nil ? RPCObject.none : RPCObject( pubKey! ), convertWith: toString ) - } - - /// returns the current packed PubKey based on the config set. - /// - /// If the config contains public keys for musig-signatures, the keys will be aggregated, otherwise the pubkey will be derrived from the signing key set. - /// - /// - Returns: the pubKey - /// - /// **Example** - /// - /// ```swift - /// let result = try Zksync(in3).pubkey() - /// // result = "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc04" - /// ``` - /// - public func pubkey() throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_pubkey", convertWith: toString ) - } - - /// returns the address of the account used. - /// - Returns: the account used. - /// - /// **Example** - /// - /// ```swift - /// let result = try Zksync(in3).accountAddress() - /// // result = "0x3b2a1bd631d9d7b17e87429a8e78dbbd9b4de292" - /// ``` - /// - public func accountAddress() throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_account_address", convertWith: toString ) - } - - /// returns the schnorr musig signature based on the current config. - /// - /// This also supports signing with multiple keys. In this case the configuration needs to sets the urls of the other keys, so the client can then excange all data needed in order to create the combined signature. - /// when exchanging the data with other keys, all known data will be send using `zk_sign` as method, but instead of the raw message a object with those data will be passed. - /// - /// - Parameter message : the message to sign - /// - Returns: The return value are 96 bytes of signature: - /// - `[0...32]` packed public key - /// - `[32..64]` r-value - /// - `[64..96]` s-value - /// - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).sign(message: "0xaabbccddeeff") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c398\ - /// // 0e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31\ - /// // b69cd0910a432156a0977c3a5baa404547e01" - /// } - /// } - /// - /// ``` - /// - public func sign(message: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_sign", params:RPCObject( message), convertWith: toString ) - } - - /// returns 0 or 1 depending on the successfull verification of the signature. - /// - /// if the `musig_pubkeys` are set it will also verify against the given public keys list. - /// - /// - Parameter message : the message which was supposed to be signed - /// - Parameter signature : the signature (96 bytes) - /// - Returns: 1 if the signature(which contains the pubkey as the first 32bytes) matches the message. - /// - /// **Example** - /// - /// ```swift - /// let result = try Zksync(in3).verify(message: "0xaabbccddeeff", signature: "0xfca80a469dbb53f8002eb1e2569d66f156f0df24d71bd589432cc7bc647bfc0493f69034c3980e7352741afa6c171b8e18355e41ed7427f6e706f8432e32e920c3e61e6c3aa00cfe0c202c29a31b69cd0910a432156a0977c3a5baa404547e01") - /// // result = 1 - /// ``` - /// - public func verify(message: String, signature: String) throws -> Int { - return try execLocalAndConvert(in3: in3, method: "zksync_verify", params:RPCObject( message), RPCObject( signature), convertWith: toInt ) - } - - /// returns the state or receipt of the the PriorityOperation - /// - Parameter opId : the opId of a layer-operstion (like depositing) - public func ethopInfo(opId: UInt64) -> Future { - return execAndConvert(in3: in3, method: "zksync_ethop_info", params:RPCObject( String(format: "0x%1x", opId)), convertWith: toString ) - } - - /// returns current token-price - /// - Parameter token : Symbol or address of the token - /// - Returns: the token price - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).getTokenPrice(token: "WBTC") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 11320.002167 - /// } - /// } - /// - /// ``` - /// - public func getTokenPrice(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_get_token_price", params:RPCObject( token), convertWith: toDouble ) - } - - /// calculates the fees for a transaction. - /// - Parameter txType : The Type of the transaction "Withdraw" or "Transfer" - /// - Parameter address : the address of the receipient - /// - Parameter token : the symbol or address of the token to pay - /// - Returns: the fees split up into single values - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).getTxFee(txType: "Transfer", address: "0xabea9132b05a70803a4e85094fd0e1800777fbef", token: "BAT") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // feeType: TransferToNew - /// // gasFee: "47684047990828528" - /// // gasPriceWei: "116000000000" - /// // gasTxAmount: "350" - /// // totalFee: "66000000000000000" - /// // zkpFee: "18378682992117666" - /// } - /// } - /// - /// ``` - /// - public func getTxFee(txType: String, address: String, token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_get_tx_fee", params:RPCObject( txType), RPCObject( address), RPCObject( token), convertWith: { try ZksyncTxFee($0,$1) } ) - } - - /// returns private key used for signing zksync-transactions - /// - Returns: the raw private key configured based on the signers seed - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).syncKey() .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x019125314fda133d5bf62cb454ee8c60927d55b68eae8b8b8bd13db814389cd6" - /// } - /// } - /// - /// ``` - /// - public func syncKey() -> Future { - return execAndConvert(in3: in3, method: "zksync_sync_key", convertWith: toString ) - } - - /// sends a deposit-transaction and returns the opId, which can be used to tradck progress. - /// - Parameter amount : the value to deposit in wei (or smallest token unit) - /// - Parameter token : the token as symbol or address - /// - Parameter approveDepositAmountForERC20 : if true and in case of an erc20-token, the client will send a approve transaction first, otherwise it is expected to be already approved. - /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. - /// - Returns: the opId. You can use `zksync_ethop_info` to follow the state-changes. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).deposit(amount: 1000, token: "WBTC") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = 74 - /// } - /// } - /// - /// ``` - /// - public func deposit(amount: UInt256, token: String, approveDepositAmountForERC20: Bool? = nil, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_deposit", params:RPCObject( amount), RPCObject( token), approveDepositAmountForERC20 == nil ? RPCObject.none : RPCObject( approveDepositAmountForERC20! ), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toUInt64 ) - } - - /// sends a zksync-transaction and returns data including the transactionHash. - /// - Parameter to : the receipient of the tokens - /// - Parameter amount : the value to transfer in wei (or smallest token unit) - /// - Parameter token : the token as symbol or address - /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. - /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).transfer(to: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1" - /// } - /// } - /// - /// ``` - /// - public func transfer(to: String, amount: UInt256, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_transfer", params:RPCObject( to), RPCObject( amount), RPCObject( token), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toString ) - } - - /// withdraws the amount to the given `ethAddress` for the given token. - /// - Parameter ethAddress : the receipient of the tokens in L1 - /// - Parameter amount : the value to transfer in wei (or smallest token unit) - /// - Parameter token : the token as symbol or address - /// - Parameter account : address of the account to send the tx from. if not specified, the first available signer will be used. - /// - Returns: the transactionHash. use `zksync_tx_info` to check the progress. - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).withdraw(ethAddress: 9.814684447173249e+47, amount: 100, token: "WBTC") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = "0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1" - /// } - /// } - /// - /// ``` - /// - public func withdraw(ethAddress: String, amount: UInt256, token: String, account: String? = nil) -> Future { - return execAndConvert(in3: in3, method: "zksync_withdraw", params:RPCObject( ethAddress), RPCObject( amount), RPCObject( token), account == nil ? RPCObject.none : RPCObject( account! ), convertWith: toString ) - } - - /// withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. - /// - Parameter token : the token as symbol or address - /// - Returns: the transactionReceipt - /// - /// **Example** - /// - /// ```swift - /// Zksync(in3).emergencyWithdraw(token: "WBTC") .observe(using: { - /// switch $0 { - /// case let .failure(err): - /// print("Failed because : \(err.localizedDescription)") - /// case let .success(val): - /// print("result : \(val)") - /// // result = - /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" - /// // blockNumber: "0x8c1e39" - /// // contractAddress: null - /// // cumulativeGasUsed: "0x2466d" - /// // gasUsed: "0x2466d" - /// // logs: - /// // - address: "0x85ec283a3ed4b66df4da23656d4bf8a507383bca" - /// // blockHash: "0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304" - /// // blockNumber: "0x8c1e39" - /// // data: 0x00000000000... - /// // logIndex: "0x0" - /// // removed: false - /// // topics: - /// // - "0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8" - /// // - "0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6" - /// // - "0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000" - /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" - /// // transactionIndex: "0x0" - /// // transactionLogIndex: "0x0" - /// // type: mined - /// // logsBloom: 0x00000000000000000000200000... - /// // root: null - /// // status: "0x1" - /// // transactionHash: "0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e" - /// // transactionIndex: "0x0" - /// } - /// } - /// - /// ``` - /// - public func emergencyWithdraw(token: String) -> Future { - return execAndConvert(in3: in3, method: "zksync_emergency_withdraw", params:RPCObject( token), convertWith: { try ZksyncTransactionReceipt($0,$1) } ) - } - - /// calculate the public key based on multiple public keys signing together using schnorr musig signatures. - /// - Parameter pubkeys : concatinated packed publickeys of the signers. the length of the bytes must be `num_keys * 32` - /// - Returns: the compact public Key - /// - /// **Example** - /// - /// ```swift - /// let result = try Zksync(in3).aggregatePubkey(pubkeys: "0x0f61bfe164cc43b5a112bfbfb0583004e79dbfafc97a7daad14c5d511fea8e2435065ddd04329ec94be682bf004b03a5a4eeca9bf50a8b8b6023942adc0b3409") - /// // result = "0x9ce5b6f8db3fbbe66a3bdbd3b4731f19ec27f80ee03ead3c0708798dd949882b" - /// ``` - /// - public func aggregatePubkey(pubkeys: String) throws -> String { - return try execLocalAndConvert(in3: in3, method: "zksync_aggregate_pubkey", params:RPCObject( pubkeys), convertWith: toString ) - } - - -} -/// fetches the contract addresses from the zksync server. This request also caches them and will return the results from cahe if available. -public struct ZksyncContractAddress { - /// the address of the govement contract - public var govContract: String - - /// the address of the main contract - public var mainContract: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - govContract = try toString(obj["govContract"],false)! - mainContract = try toString(obj["mainContract"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["govContract"] = RPCObject( govContract ) - obj["mainContract"] = RPCObject( mainContract ) - return obj - } - - /// initialize the ZksyncContractAddress - /// - /// - Parameter govContract : the address of the govement contract - /// - Parameter mainContract : the address of the main contract - public init(govContract: String, mainContract: String) { - self.govContract = govContract - self.mainContract = mainContract - } -} - -/// a array of tokens-definitions. This request also caches them and will return the results from cahe if available. -public struct ZksyncTokens { - /// the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) - public var address: String - - /// decimals to be used when formating it for human readable representation. - public var decimals: Int - - /// id which will be used when encoding the token. - public var id: UInt64 - - /// symbol for the token - public var symbol: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - address = try toString(obj["address"],false)! - decimals = try toInt(obj["decimals"],false)! - id = try toUInt64(obj["id"],false)! - symbol = try toString(obj["symbol"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject( address ) - obj["decimals"] = RPCObject( String(format: "0x%1x", arguments: [decimals]) ) - obj["id"] = RPCObject( String(format: "0x%1x", arguments: [id]) ) - obj["symbol"] = RPCObject( symbol ) - return obj - } - - /// initialize the ZksyncTokens - /// - /// - Parameter address : the address of the ERC2-Contract or 0x00000..000 in case of the native token (eth) - /// - Parameter decimals : decimals to be used when formating it for human readable representation. - /// - Parameter id : id which will be used when encoding the token. - /// - Parameter symbol : symbol for the token - public init(address: String, decimals: Int, id: UInt64, symbol: String) { - self.address = address - self.decimals = decimals - self.id = id - self.symbol = symbol - } -} - -/// the current state of the requested account. -public struct ZksyncAccountInfo { - /// the address of the account - public var address: String - - /// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. - public var commited: ZksyncCommited - - /// the state of all depositing-tx. - public var depositing: ZksyncDepositing - - /// the assigned id of the account, which will be used when encoding it into the rollup. - public var id: UInt64 - - /// the state after the rollup was verified in L1. - public var verified: ZksyncVerified - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - address = try toString(obj["address"],false)! - commited = try ZksyncCommited(obj["commited"],false)! - depositing = try ZksyncDepositing(obj["depositing"],false)! - id = try toUInt64(obj["id"],false)! - verified = try ZksyncVerified(obj["verified"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject( address ) - obj["id"] = RPCObject( String(format: "0x%1x", arguments: [id]) ) - return obj - } - - /// initialize the ZksyncAccountInfo - /// - /// - Parameter address : the address of the account - /// - Parameter commited : the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. - /// - Parameter depositing : the state of all depositing-tx. - /// - Parameter id : the assigned id of the account, which will be used when encoding it into the rollup. - /// - Parameter verified : the state after the rollup was verified in L1. - public init(address: String, commited: ZksyncCommited, depositing: ZksyncDepositing, id: UInt64, verified: ZksyncVerified) { - self.address = address - self.commited = commited - self.depositing = depositing - self.id = id - self.verified = verified - } -} - -/// the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. -public struct ZksyncCommited { - /// the token-balance - public var balances: [String:UInt256] - - /// the nonce or transaction count. - public var nonce: UInt64 - - /// the pubKeyHash set for the requested account or `0x0000...` if not set yet. - public var pubKeyHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) - nonce = try toUInt64(obj["nonce"],false)! - pubKeyHash = try toString(obj["pubKeyHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["pubKeyHash"] = RPCObject( pubKeyHash ) - return obj - } - - /// initialize the ZksyncCommited - /// - /// - Parameter balances : the token-balance - /// - Parameter nonce : the nonce or transaction count. - /// - Parameter pubKeyHash : the pubKeyHash set for the requested account or `0x0000...` if not set yet. - public init(balances: [String:UInt256], nonce: UInt64, pubKeyHash: String) { - self.balances = balances - self.nonce = nonce - self.pubKeyHash = pubKeyHash - } -} - -/// the state of all depositing-tx. -public struct ZksyncDepositing { - /// the token-values. - public var balances: [String:UInt256] - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) - } - - - /// initialize the ZksyncDepositing - /// - /// - Parameter balances : the token-values. - public init(balances: [String:UInt256]) { - self.balances = balances - } -} - -/// the state after the rollup was verified in L1. -public struct ZksyncVerified { - /// the token-balances. - public var balances: [String:UInt256] - - /// the nonce or transaction count. - public var nonce: UInt64 - - /// the pubKeyHash set for the requested account or `0x0000...` if not set yet. - public var pubKeyHash: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - balances = try toObject(obj["balances"])!.mapValues({ try toUInt256($0,false)! }) - nonce = try toUInt64(obj["nonce"],false)! - pubKeyHash = try toString(obj["pubKeyHash"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["nonce"] = RPCObject( String(format: "0x%1x", arguments: [nonce]) ) - obj["pubKeyHash"] = RPCObject( pubKeyHash ) - return obj - } - - /// initialize the ZksyncVerified - /// - /// - Parameter balances : the token-balances. - /// - Parameter nonce : the nonce or transaction count. - /// - Parameter pubKeyHash : the pubKeyHash set for the requested account or `0x0000...` if not set yet. - public init(balances: [String:UInt256], nonce: UInt64, pubKeyHash: String) { - self.balances = balances - self.nonce = nonce - self.pubKeyHash = pubKeyHash - } -} - -/// the current state of the requested tx. -public struct ZksyncTxInfo { - /// the blockNumber containing the tx or `null` if still pending - public var block: UInt64 - - /// true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. - public var executed: Bool - - /// if executed, this property marks the success of the tx. - public var success: Bool - - /// if executed and failed this will include an error message - public var failReason: String - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - block = try toUInt64(obj["block"],false)! - executed = try toBool(obj["executed"],false)! - success = try toBool(obj["success"],false)! - failReason = try toString(obj["failReason"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["block"] = RPCObject( String(format: "0x%1x", arguments: [block]) ) - obj["executed"] = RPCObject( executed ) - obj["success"] = RPCObject( success ) - obj["failReason"] = RPCObject( failReason ) - return obj - } - - /// initialize the ZksyncTxInfo - /// - /// - Parameter block : the blockNumber containing the tx or `null` if still pending - /// - Parameter executed : true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. - /// - Parameter success : if executed, this property marks the success of the tx. - /// - Parameter failReason : if executed and failed this will include an error message - public init(block: UInt64, executed: Bool, success: Bool, failReason: String) { - self.block = block - self.executed = executed - self.success = success - self.failReason = failReason - } -} - -/// the fees split up into single values -public struct ZksyncTxFee { - /// Type of the transaaction - public var feeType: String - - /// the gas for the core-transaction - public var gasFee: UInt64 - - /// current gasPrice - public var gasPriceWei: UInt64 - - /// gasTxAmount - public var gasTxAmount: UInt64 - - /// total of all fees needed to pay in order to execute the transaction - public var totalFee: UInt64 - - /// zkpFee - public var zkpFee: UInt64 - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - feeType = try toString(obj["feeType"],false)! - gasFee = try toUInt64(obj["gasFee"],false)! - gasPriceWei = try toUInt64(obj["gasPriceWei"],false)! - gasTxAmount = try toUInt64(obj["gasTxAmount"],false)! - totalFee = try toUInt64(obj["totalFee"],false)! - zkpFee = try toUInt64(obj["zkpFee"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["feeType"] = RPCObject( feeType ) - obj["gasFee"] = RPCObject( String(format: "0x%1x", arguments: [gasFee]) ) - obj["gasPriceWei"] = RPCObject( String(format: "0x%1x", arguments: [gasPriceWei]) ) - obj["gasTxAmount"] = RPCObject( String(format: "0x%1x", arguments: [gasTxAmount]) ) - obj["totalFee"] = RPCObject( String(format: "0x%1x", arguments: [totalFee]) ) - obj["zkpFee"] = RPCObject( String(format: "0x%1x", arguments: [zkpFee]) ) - return obj - } - - /// initialize the ZksyncTxFee - /// - /// - Parameter feeType : Type of the transaaction - /// - Parameter gasFee : the gas for the core-transaction - /// - Parameter gasPriceWei : current gasPrice - /// - Parameter gasTxAmount : gasTxAmount - /// - Parameter totalFee : total of all fees needed to pay in order to execute the transaction - /// - Parameter zkpFee : zkpFee - public init(feeType: String, gasFee: UInt64, gasPriceWei: UInt64, gasTxAmount: UInt64, totalFee: UInt64, zkpFee: UInt64) { - self.feeType = feeType - self.gasFee = gasFee - self.gasPriceWei = gasPriceWei - self.gasTxAmount = gasTxAmount - self.totalFee = totalFee - self.zkpFee = zkpFee - } -} - -/// the transactionReceipt -public struct ZksyncTransactionReceipt { - /// the blockNumber - public var blockNumber: UInt64 - - /// blockhash if ther containing block - public var blockHash: String - - /// the deployed contract in case the tx did deploy a new contract - public var contractAddress: String? - - /// gas used for all transaction up to this one in the block - public var cumulativeGasUsed: UInt64 - - /// gas used by this transaction. - public var gasUsed: UInt64 - - /// array of events created during execution of the tx - public var logs: [ZksyncEthlog] - - /// bloomfilter used to detect events for `eth_getLogs` - public var logsBloom: String - - /// error-status of the tx. 0x1 = success 0x0 = failure - public var status: Int - - /// requested transactionHash - public var transactionHash: String - - /// transactionIndex within the containing block. - public var transactionIndex: Int - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - blockNumber = try toUInt64(obj["blockNumber"],false)! - blockHash = try toString(obj["blockHash"],false)! - contractAddress = try toString(obj["contractAddress"],true)! - cumulativeGasUsed = try toUInt64(obj["cumulativeGasUsed"],false)! - gasUsed = try toUInt64(obj["gasUsed"],false)! - logs = try toArray(obj["logs"])!.map({ try ZksyncEthlog($0,false)! }) - logsBloom = try toString(obj["logsBloom"],false)! - status = try toInt(obj["status"],false)! - transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toInt(obj["transactionIndex"],false)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - obj["blockHash"] = RPCObject( blockHash ) - if let x = contractAddress { obj["contractAddress"] = RPCObject( x ) } - obj["cumulativeGasUsed"] = RPCObject( String(format: "0x%1x", arguments: [cumulativeGasUsed]) ) - obj["gasUsed"] = RPCObject( String(format: "0x%1x", arguments: [gasUsed]) ) - obj["logsBloom"] = RPCObject( logsBloom ) - obj["status"] = RPCObject( String(format: "0x%1x", arguments: [status]) ) - obj["transactionHash"] = RPCObject( transactionHash ) - obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) - return obj - } - - /// initialize the ZksyncTransactionReceipt - /// - /// - Parameter blockNumber : the blockNumber - /// - Parameter blockHash : blockhash if ther containing block - /// - Parameter contractAddress : the deployed contract in case the tx did deploy a new contract - /// - Parameter cumulativeGasUsed : gas used for all transaction up to this one in the block - /// - Parameter gasUsed : gas used by this transaction. - /// - Parameter logs : array of events created during execution of the tx - /// - Parameter logsBloom : bloomfilter used to detect events for `eth_getLogs` - /// - Parameter status : error-status of the tx. 0x1 = success 0x0 = failure - /// - Parameter transactionHash : requested transactionHash - /// - Parameter transactionIndex : transactionIndex within the containing block. - public init(blockNumber: UInt64, blockHash: String, contractAddress: String? = nil, cumulativeGasUsed: UInt64, gasUsed: UInt64, logs: [ZksyncEthlog], logsBloom: String, status: Int, transactionHash: String, transactionIndex: Int) { - self.blockNumber = blockNumber - self.blockHash = blockHash - self.contractAddress = contractAddress - self.cumulativeGasUsed = cumulativeGasUsed - self.gasUsed = gasUsed - self.logs = logs - self.logsBloom = logsBloom - self.status = status - self.transactionHash = transactionHash - self.transactionIndex = transactionIndex - } -} - -/// array of events created during execution of the tx -public struct ZksyncEthlog { - /// the address triggering the event. - public var address: String - - /// the blockNumber - public var blockNumber: UInt64 - - /// blockhash if ther containing block - public var blockHash: String - - /// abi-encoded data of the event (all non indexed fields) - public var data: String - - /// the index of the even within the block. - public var logIndex: Int - - /// the reorg-status of the event. - public var removed: Bool - - /// array of 32byte-topics of the indexed fields. - public var topics: [String] - - /// requested transactionHash - public var transactionHash: String - - /// transactionIndex within the containing block. - public var transactionIndex: Int - - /// index of the event within the transaction. - public var transactionLogIndex: Int? - - /// mining-status - public var type: String? - - internal init?(_ rpc:RPCObject?, _ optional: Bool = true) throws { - guard let obj = try toObject(rpc, optional) else { return nil } - address = try toString(obj["address"],false)! - blockNumber = try toUInt64(obj["blockNumber"],false)! - blockHash = try toString(obj["blockHash"],false)! - data = try toString(obj["data"],false)! - logIndex = try toInt(obj["logIndex"],false)! - removed = try toBool(obj["removed"],false)! - topics = try toArray(obj["topics"])!.map({ try toString($0,false)! }) - transactionHash = try toString(obj["transactionHash"],false)! - transactionIndex = try toInt(obj["transactionIndex"],false)! - transactionLogIndex = try toInt(obj["transactionLogIndex"],true)! - type = try toString(obj["type"],true)! - } - - internal func toRPCDict() -> [String:RPCObject] { - var obj:[String:RPCObject] = [:] - obj["address"] = RPCObject( address ) - obj["blockNumber"] = RPCObject( String(format: "0x%1x", arguments: [blockNumber]) ) - obj["blockHash"] = RPCObject( blockHash ) - obj["data"] = RPCObject( data ) - obj["logIndex"] = RPCObject( String(format: "0x%1x", arguments: [logIndex]) ) - obj["removed"] = RPCObject( removed ) - obj["topics"] = RPCObject( topics ) - obj["transactionHash"] = RPCObject( transactionHash ) - obj["transactionIndex"] = RPCObject( String(format: "0x%1x", arguments: [transactionIndex]) ) - if let x = transactionLogIndex { obj["transactionLogIndex"] = RPCObject( String(format: "0x%1x", arguments: [x]) ) } - if let x = type { obj["type"] = RPCObject( x ) } - return obj - } - - /// initialize the ZksyncEthlog - /// - /// - Parameter address : the address triggering the event. - /// - Parameter blockNumber : the blockNumber - /// - Parameter blockHash : blockhash if ther containing block - /// - Parameter data : abi-encoded data of the event (all non indexed fields) - /// - Parameter logIndex : the index of the even within the block. - /// - Parameter removed : the reorg-status of the event. - /// - Parameter topics : array of 32byte-topics of the indexed fields. - /// - Parameter transactionHash : requested transactionHash - /// - Parameter transactionIndex : transactionIndex within the containing block. - /// - Parameter transactionLogIndex : index of the event within the transaction. - /// - Parameter type : mining-status - public init(address: String, blockNumber: UInt64, blockHash: String, data: String, logIndex: Int, removed: Bool, topics: [String], transactionHash: String, transactionIndex: Int, transactionLogIndex: Int? = nil, type: String? = nil) { - self.address = address - self.blockNumber = blockNumber - self.blockHash = blockHash - self.data = data - self.logIndex = logIndex - self.removed = removed - self.topics = topics - self.transactionHash = transactionHash - self.transactionIndex = transactionIndex - self.transactionLogIndex = transactionLogIndex - self.type = type - } -} \ No newline at end of file diff --git a/swift/Sources/In3/Config.swift b/swift/Sources/In3/Config.swift deleted file mode 100644 index 958eb8f4f..000000000 --- a/swift/Sources/In3/Config.swift +++ /dev/null @@ -1,429 +0,0 @@ -// This is a generated file, please don't edit it manually! - -import Foundation - -/// The main Incubed Configuration -public struct In3Config : Codable { - - /// create a new Incubed Client based on the Configuration - public func createClient() throws -> In3 { - return try In3(self) - } - - - /// the chainId or the name of a known chain. It defines the nodelist to connect to. - /// (default: `"mainnet"`) - /// - /// Possible Values are: - /// - /// - `mainnet` : Mainnet Chain - /// - `goerli` : Goerli Testnet - /// - `ewc` : Energy WebFoundation - /// - `btc` : Bitcoin - /// - `ipfs` : ipfs - /// - `local` : local-chain - /// - /// - /// Example: `goerli` - public var chainId : String? - - /// the number in percent needed in order reach finality (% of signature of the validators). - /// - /// Example: `50` - public var finality : Int? - - /// if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. - /// - /// Example: `true` - public var includeCode : Bool? - - /// max number of attempts in case a response is rejected. - /// (default: `7`) - /// - /// Example: `1` - public var maxAttempts : Int? - - /// if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. - /// - /// Example: `true` - public var keepIn3 : Bool? - - /// if true, requests sent will be used for stats. - /// (default: `true`) - public var stats : Bool? - - /// if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. - /// - /// Example: `true` - public var useBinary : Bool? - - /// iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. - /// - /// Example: `true` - public var experimental : Bool? - - /// specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. - /// (default: `20000`) - /// - /// Example: `100000` - public var timeout : UInt64? - - /// if true the nodes should send a proof of the response. If set to none, verification is turned off completly. - /// (default: `"standard"`) - /// - /// Possible Values are: - /// - /// - `none` : no proof will be generated or verfiied. This also works with standard rpc-endpoints. - /// - `standard` : Stanbdard Proof means all important properties are verfiied - /// - `full` : In addition to standard, also some rarly needed properties are verfied, like uncles. But this causes a bigger payload. - /// - /// - /// Example: `none` - public var proof : String? - - /// if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. - /// - /// Example: `6` - public var replaceLatestBlock : Int? - - /// if true the nodelist will be automaticly updated if the lastBlock is newer. - /// (default: `true`) - public var autoUpdateList : Bool? - - /// number of signatures requested in order to verify the blockhash. - /// (default: `1`) - /// - /// Example: `2` - public var signatureCount : Int? - - /// if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. - /// (default: `true`) - /// - /// Example: `true` - public var bootWeights : Bool? - - /// if true the client will try to use http instead of https. - /// - /// Example: `true` - public var useHttp : Bool? - - /// min stake of the server. Only nodes owning at least this amount will be chosen. - /// - /// Example: `10000000` - public var minDeposit : UInt256? - - /// used to identify the capabilities of the node. - /// - /// Example: `"0xffff"` - public var nodeProps : String? - - /// the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. - /// (default: `2`) - /// - /// Example: `3` - public var requestCount : Int? - - /// url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. - /// - /// Example: `http://loalhost:8545` - public var rpc : String? - - /// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. - /// - /// Example: `contract: "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f" - /// nodeList: - /// - address: "0x45d45e6ff99e6c34a235d263965910298985fcfe" - /// url: https://in3-v2.slock.it/mainnet/nd-1 - /// props: "0xFFFF"` - public var nodes : Nodes? - - /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). - /// - /// Example: - /// ``` - /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" - /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" - /// signer_type: contract - /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" - /// sync_key: "0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816" - /// signer_type: create2 - /// create2: - /// creator: "0x6487c3ae644703c1f07527c18fe5569592654bcb" - /// saltarg: "0xb90306e2391fefe48aa89a8e91acbca502a94b2d734acc3335bb2ff5c266eb12" - /// codehash: "0xd6af3ee91c96e29ddab0d4cb9b5dd3025caf84baad13bef7f2b87038d38251e5" - /// account: "0x995628aa92d6a016da55e7de8b1727e1eb97d337" - /// signer_type: pk - /// musig_pub_keys: 0x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d8160x9ad89ac0643ffdc32b2dab859ad0f9f7e4057ec23c2b17699c9b27eff331d816 - /// sync_key: "0xe8f2ee64be83c0ab9466b0490e4888dbf5a070fd1d82b567e33ebc90457a5734" - /// musig_urls: - /// - null - /// - https://approver.service.com - /// ``` - public var zksync : Zksync? - - /// the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) - /// - /// Example: `"0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe"` - public var key : String? - - /// registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) - /// - /// Example: - /// ``` - /// "0xc9564409cbfca3f486a07996e8015124f30ff8331fc6dcbd610a050f1f983afe" - /// ``` - public var pk : String? - - /// configure the Bitcoin verification - /// - /// Example: `maxDAP: 30 - /// maxDiff: 5` - public var btc : Btc? - - /// initialize it memberwise - /// - Parameter chainId : the chainId or the name of a known chain. It defines the nodelist to connect to. - /// - Parameter finality : the number in percent needed in order reach finality (% of signature of the validators). - /// - Parameter includeCode : if true, the request should include the codes of all accounts. otherwise only the the codeHash is returned. In this case the client may ask by calling eth_getCode() afterwards. - /// - Parameter maxAttempts : max number of attempts in case a response is rejected. - /// - Parameter keepIn3 : if true, requests sent to the input sream of the comandline util will be send theor responses in the same form as the server did. - /// - Parameter stats : if true, requests sent will be used for stats. - /// - Parameter useBinary : if true the client will use binary format. This will reduce the payload of the responses by about 60% but should only be used for embedded systems or when using the API, since this format does not include the propertynames anymore. - /// - Parameter experimental : iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. - /// - Parameter timeout : specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. - /// - Parameter proof : if true the nodes should send a proof of the response. If set to none, verification is turned off completly. - /// - Parameter replaceLatestBlock : if specified, the blocknumber *latest* will be replaced by blockNumber- specified value. - /// - Parameter autoUpdateList : if true the nodelist will be automaticly updated if the lastBlock is newer. - /// - Parameter signatureCount : number of signatures requested in order to verify the blockhash. - /// - Parameter bootWeights : if true, the first request (updating the nodelist) will also fetch the current health status and use it for blacklisting unhealthy nodes. This is used only if no nodelist is availabkle from cache. - /// - Parameter useHttp : if true the client will try to use http instead of https. - /// - Parameter minDeposit : min stake of the server. Only nodes owning at least this amount will be chosen. - /// - Parameter nodeProps : used to identify the capabilities of the node. - /// - Parameter requestCount : the number of request send in parallel when getting an answer. More request will make it more expensive, but increase the chances to get a faster answer, since the client will continue once the first verifiable response was received. - /// - Parameter rpc : url of one or more direct rpc-endpoints to use. (list can be comma seperated). If this is used, proof will automaticly be turned off. - /// - Parameter nodes : defining the nodelist. collection of JSON objects with chain Id (hex string) as key. - /// - Parameter zksync : configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). - /// - Parameter key : the client key to sign requests. (only availble if build with `-DPK_SIGNER=true` , which is on per default) - /// - Parameter pk : registers raw private keys as signers for transactions. (only availble if build with `-DPK_SIGNER=true` , which is on per default) - /// - Parameter btc : configure the Bitcoin verification - public init(chainId : String? = nil, finality : Int? = nil, includeCode : Bool? = nil, maxAttempts : Int? = nil, keepIn3 : Bool? = nil, stats : Bool? = nil, useBinary : Bool? = nil, experimental : Bool? = nil, timeout : UInt64? = nil, proof : String? = nil, replaceLatestBlock : Int? = nil, autoUpdateList : Bool? = nil, signatureCount : Int? = nil, bootWeights : Bool? = nil, useHttp : Bool? = nil, minDeposit : UInt256? = nil, nodeProps : String? = nil, requestCount : Int? = nil, rpc : String? = nil, nodes : Nodes? = nil, zksync : Zksync? = nil, key : String? = nil, pk : String? = nil, btc : Btc? = nil) { - self.chainId = chainId - self.finality = finality - self.includeCode = includeCode - self.maxAttempts = maxAttempts - self.keepIn3 = keepIn3 - self.stats = stats - self.useBinary = useBinary - self.experimental = experimental - self.timeout = timeout - self.proof = proof - self.replaceLatestBlock = replaceLatestBlock - self.autoUpdateList = autoUpdateList - self.signatureCount = signatureCount - self.bootWeights = bootWeights - self.useHttp = useHttp - self.minDeposit = minDeposit - self.nodeProps = nodeProps - self.requestCount = requestCount - self.rpc = rpc - self.nodes = nodes - self.zksync = zksync - self.key = key - self.pk = pk - self.btc = btc - } - - /// defining the nodelist. collection of JSON objects with chain Id (hex string) as key. - public struct Nodes : Codable { - - /// address of the registry contract. (This is the data-contract!) - public var contract : String - - /// address of the whiteList contract. This cannot be combined with whiteList! - public var whiteListContract : String? - - /// manual whitelist. - public var whiteList : [String]? - - /// identifier of the registry. - public var registryId : String - - /// if set, the nodeList will be updated before next request. - public var needsUpdate : Bool? - - /// average block time (seconds) for this chain. - public var avgBlockTime : Int? - - /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. - public var verifiedHashes : [VerifiedHashes]? - - /// manual nodeList. As Value a array of Node-Definitions is expected. - public var nodeList : [NodeList]? - - /// initialize it memberwise - /// - Parameter contract : defining the nodelist. collection of JSON objects with chain Id (hex string) as key. - /// - Parameter whiteListContract : address of the whiteList contract. This cannot be combined with whiteList! - /// - Parameter whiteList : manual whitelist. - /// - Parameter registryId : identifier of the registry. - /// - Parameter needsUpdate : if set, the nodeList will be updated before next request. - /// - Parameter avgBlockTime : average block time (seconds) for this chain. - /// - Parameter verifiedHashes : if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. - /// - Parameter nodeList : manual nodeList. As Value a array of Node-Definitions is expected. - public init(contract : String, whiteListContract : String? = nil, whiteList : [String]? = nil, registryId : String, needsUpdate : Bool? = nil, avgBlockTime : Int? = nil, verifiedHashes : [VerifiedHashes]? = nil, nodeList : [NodeList]? = nil) { - self.contract = contract - self.whiteListContract = whiteListContract - self.whiteList = whiteList - self.registryId = registryId - self.needsUpdate = needsUpdate - self.avgBlockTime = avgBlockTime - self.verifiedHashes = verifiedHashes - self.nodeList = nodeList - } - } - - /// if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. - public struct VerifiedHashes : Codable { - - /// block number - public var block : UInt64 - - /// verified hash corresponding to block number. - public var hash : String - - /// initialize it memberwise - /// - Parameter block : if the client sends an array of blockhashes the server will not deliver any signatures or blockheaders for these blocks, but only return a string with a number. This is automaticly updated by the cache, but can be overriden per request. - /// - Parameter hash : verified hash corresponding to block number. - public init(block : UInt64, hash : String) { - self.block = block - self.hash = hash - } - } - - /// manual nodeList. As Value a array of Node-Definitions is expected. - public struct NodeList : Codable { - - /// URL of the node. - public var url : String - - /// address of the node - public var address : String - - /// used to identify the capabilities of the node (defaults to 0xFFFF). - public var props : String - - /// initialize it memberwise - /// - Parameter url : manual nodeList. As Value a array of Node-Definitions is expected. - /// - Parameter address : address of the node - /// - Parameter props : used to identify the capabilities of the node (defaults to 0xFFFF). - public init(url : String, address : String, props : String) { - self.url = url - self.address = address - self.props = props - } - } - - /// configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). - public struct Zksync : Codable { - - /// url of the zksync-server (if not defined it will be choosen depending on the chain) - /// (default: `"https://api.zksync.io/jsrpc"`) - public var provider_url : String? - - /// the account to be used. if not specified, the first signer will be used. - public var account : String? - - /// the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. - public var sync_key : String? - - /// address of the main contract- If not specified it will be taken from the server. - public var main_contract : String? - - /// type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. - /// (default: `"pk"`) - /// - /// Possible Values are: - /// - /// - `pk` : Private matching the account is used ( for EOA) - /// - `contract` : Contract Signature based EIP 1271 - /// - `create2` : create2 optionas are used - /// - public var signer_type : String? - - /// concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. - public var musig_pub_keys : String? - - /// a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. - public var musig_urls : [String]? - - /// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. - public var create2 : Create2? - - /// initialize it memberwise - /// - Parameter provider_url : configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per default). - /// - Parameter account : the account to be used. if not specified, the first signer will be used. - /// - Parameter sync_key : the seed used to generate the sync_key. This way you can explicitly set the pk instead of derriving it from a signer. - /// - Parameter main_contract : address of the main contract- If not specified it will be taken from the server. - /// - Parameter signer_type : type of the account. Must be either `pk`(default), `contract` (using contract signatures) or `create2` using the create2-section. - /// - Parameter musig_pub_keys : concatenated packed public keys (32byte) of the musig signers. if set the pubkey and pubkeyhash will based on the aggregated pubkey. Also the signing will use multiple keys. - /// - Parameter musig_urls : a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. - /// - Parameter create2 : create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. - public init(provider_url : String? = nil, account : String? = nil, sync_key : String? = nil, main_contract : String? = nil, signer_type : String? = nil, musig_pub_keys : String? = nil, musig_urls : [String]? = nil, create2 : Create2? = nil) { - self.provider_url = provider_url - self.account = account - self.sync_key = sync_key - self.main_contract = main_contract - self.signer_type = signer_type - self.musig_pub_keys = musig_pub_keys - self.musig_urls = musig_urls - self.create2 = create2 - } - } - - /// create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. - public struct Create2 : Codable { - - /// The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory ) - public var creator : String - - /// a salt-argument, which will be added to the pubkeyhash and create the create2-salt. - public var saltarg : String - - /// the hash of the actual deploy-tx including the constructor-arguments. - public var codehash : String - - /// initialize it memberwise - /// - Parameter creator : create2-arguments for sign_type `create2`. This will allow to sign for contracts which are not deployed yet. - /// - Parameter saltarg : a salt-argument, which will be added to the pubkeyhash and create the create2-salt. - /// - Parameter codehash : the hash of the actual deploy-tx including the constructor-arguments. - public init(creator : String, saltarg : String, codehash : String) { - self.creator = creator - self.saltarg = saltarg - self.codehash = codehash - } - } - - /// configure the Bitcoin verification - public struct Btc : Codable { - - /// max number of DAPs (Difficulty Adjustment Periods) allowed when accepting new targets. - /// (default: `20`) - /// - /// Example: `10` - public var maxDAP : Int? - - /// max increase (in percent) of the difference between targets when accepting new targets. - /// (default: `10`) - /// - /// Example: `5` - public var maxDiff : Int? - - /// initialize it memberwise - /// - Parameter maxDAP : configure the Bitcoin verification - /// - Parameter maxDiff : max increase (in percent) of the difference between targets when accepting new targets. - public init(maxDAP : Int? = nil, maxDiff : Int? = nil) { - self.maxDAP = maxDAP - self.maxDiff = maxDiff - } - } - - -} diff --git a/swift/Sources/In3/In3.swift b/swift/Sources/In3/In3.swift deleted file mode 100644 index 280daecee..000000000 --- a/swift/Sources/In3/In3.swift +++ /dev/null @@ -1,91 +0,0 @@ -import CIn3 -import Foundation - -/// The Incubed client -public class In3 { - internal var in3: UnsafeMutablePointer? = nil - /// the transport function - public var transport: (_ url: String, _ method:String, _ payload:Data?, _ headers: [String], _ cb: @escaping (_ data:TransportResult)->Void) -> Void - - /// set the cache impementation. - /// - /// the default is usually the FileCache storing data in the users home-directory, but by implementing the IN3Cache Protocol any custom storage is supported. - var cache: In3Cache? { - get { - return defaultCache - } - set(value) { - defaultCache = value - } - } - - /// initialize with a Configurations - public init(_ config: In3Config) throws { - transport = httpTransfer - in3 = in3_for_chain_auto_init(1) - try configure(config) - try registerCache(self) - } - - deinit { - in3_free(in3) - } - - /// change the configuration. - /// - Paramater config : the partial or full Configuration to change. - public func configure(_ config: In3Config) throws { - let jsonConfig = try JSONEncoder().encode(config) - let error = in3_configure(in3, String(decoding: jsonConfig, as: UTF8.self)) - if let msg = error { - throw IncubedError.config(message: String(cString: msg)) - } - } - - /// Execute a request directly and local. - /// This works only for requests which do not need to be send to a server. - public func execLocal(_ method: String, _ params: RPCObject...) throws -> RPCObject { - return try execLocal(method, params) - } - - /// Execute a request directly and local. - /// This works only for requests which do not need to be send to a server. - public func execLocal(_ method: String, _ params: [RPCObject]) throws -> RPCObject { - let jsonReqData = try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))) - let rawResult = executeJSON(String(decoding: jsonReqData, as: UTF8.self)) - let response = try JSONDecoder().decode(JSONResponse.self, from: rawResult.data(using: .utf8)!) - if let error = response.error { - throw IncubedError.rpc(message: error.message) - } - else if let result = response.result { - return RPCObject(result) - } - else { - throw IncubedError.rpc(message: "No Result in response") - } - } - - - /// executes a asnychronous request - /// - /// This requires a transport to be set - /// - Parameter method : the rpc-method to call - /// - Parameter params : the paramas as ROCPobjects - /// - Parameter cb : the callback which will be called with a Result (either success or error ) when done. - public func exec(_ method: String, _ params: RPCObject..., cb: @escaping (_ result:RequestResult)->Void) throws { - try In3Request(method,params,self,cb).exec() - } - - /// executes a json-rpc encoded request synchonously and returns the result as json-string - public func executeJSON(_ rpc: String) -> String { - return rpc.withCString { (baseAddress)->String in - let count = rpc.utf8.count + 1 - let cstr = UnsafeMutablePointer.allocate(capacity: count) - defer { - cstr.deallocate() - } - cstr.initialize(from: baseAddress, count: count) - return String(cString: in3_client_exec_req(in3, cstr)) - } - } -} - diff --git a/swift/Sources/In3/Utils/Cache.swift b/swift/Sources/In3/Utils/Cache.swift deleted file mode 100644 index 55bf0a5e3..000000000 --- a/swift/Sources/In3/Utils/Cache.swift +++ /dev/null @@ -1,97 +0,0 @@ -import Foundation -import CIn3 - -/// Protocol for Cache-Implementation. -/// The cache is used to store data like nodelists and their reputations, contract codes and more. -/// those calls a synchronous calls and should be fast. -/// in order to set the cache, use the `In3.cache`-property. -public protocol In3Cache { - - /// find the data for the given cache-key or `nil`if not found. - func getEntry(key:String)->Data? - - /// write the data to the cache using the given key.. - func setEntry(key:String,value:Data)->Void - - /// clears all cache entries - func clear()->Void -} - -/// File-Implementation for the cache. -public class FileCache : In3Cache { - var dir:URL - - /// creates the cache-directory in the USers home-directory with hte name `.in3` - convenience init() throws { - try self.init(URL(fileURLWithPath: ".in3", relativeTo: FileManager.default.homeDirectoryForCurrentUser)) - } - - /// caches data in the given directory - convenience init(_ dir:String) throws { - try self.init(URL(fileURLWithPath: dir, isDirectory: true)) - } - - /// caches data in the given directory - init(_ dir:URL) throws { - try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) - self.dir = dir - } - - /// write the data to the cache using the given key.. - public func setEntry(key: String, value: Data) { - try? value.write(to: URL(fileURLWithPath: key, relativeTo: dir)) - } - - /// find the data for the given cache-key or `nil`if not found. - public func getEntry(key: String) -> Data? { - return try? Data(contentsOf: URL(fileURLWithPath: key, relativeTo: dir)) - } - - /// clears all cache entries - public func clear() { - try? FileManager.default.removeItem(at: dir) - try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) - } -} - -internal var defaultCache:In3Cache? - -internal func registerCache(_ in3:In3) throws { - if defaultCache == nil { - defaultCache = try FileCache() - } - var cbs = swift_cb_t( - cache_get: { ctx -> in3_ret_t in - let key = String(cString: ctx.pointee.key) - if let cache = defaultCache, - let data = cache.getEntry(key: key) { - data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer ) in - ctx.pointee.content = b_new(ptr.baseAddress?.assumingMemoryBound(to: UInt8.self), UInt32(data.count)) - } - return IN3_OK - } else { - return IN3_EIGNORE - } - }, - cache_set: { ctx -> in3_ret_t in - let key = String(cString: ctx.pointee.key) - if let cache = defaultCache { - cache.setEntry(key: key, value: Data(bytes: ctx.pointee.content.pointee.data, count: Int(ctx.pointee.content.pointee.len))) - return IN3_OK - } - return IN3_EIGNORE - }, - cache_clear: { - if let cache = defaultCache { - cache.clear() - } - return IN3_OK - } - ) - - if let in3ptr = in3.in3 { - in3_register_swift(in3ptr, &cbs) - } - -} - diff --git a/swift/Sources/In3/Utils/Convert.swift b/swift/Sources/In3/Utils/Convert.swift deleted file mode 100644 index 3056bcab4..000000000 --- a/swift/Sources/In3/Utils/Convert.swift +++ /dev/null @@ -1,258 +0,0 @@ - -import Foundation - - -/// converts a RPC-Object to UInt64 or throws -internal func toUInt64(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt64?{ - if let data = data { - switch data { - case let .integer(val): - return UInt64(val) - case let .string(val): - if let intVal = UInt64(val) { - return intVal - } else if val.hasPrefix("0x"), let intVal = UInt64(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { - return intVal - } else { - throw IncubedError.config(message: "Can not convert '\(val)' to int") - } - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for Int") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - - -/// converts a RPC-Object to UInt256 or throws -internal func toUInt256(_ data:RPCObject?, _ optional:Bool = true) throws -> UInt256?{ - if let data = data { - switch data { - case let .integer(val): - return UInt256(val) - case let .string(val): - if let intVal = UInt256(val) { - return intVal - } else { - throw IncubedError.config(message: "Can not convert '\(val)' to uint256") - } - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for Int") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - - -/// converts a RPC-Object to UInt64 or throws -internal func toInt(_ data:RPCObject?, _ optional:Bool = true) throws -> Int?{ - if let data = data { - switch data { - case let .integer(val): - return val - case let .string(val): - if let intVal = Int(val) { - return intVal - } else if val.hasPrefix("0x"), let intVal = Int(val.suffix(from: val.index( val.startIndex, offsetBy: 2)), radix: 16) { - return intVal - } else { - throw IncubedError.config(message: "Can not convert '\(val)' to int") - } - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for Int") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - -/// converts a RPC-Object to Double or throws -internal func toDouble(_ data:RPCObject?, _ optional:Bool = true) throws -> Double?{ - if let data = data { - switch data { - case let .integer(val): - return Double(val) - case let .double(val): - return val - case let .string(val): - if let intVal = Double(val) { - return intVal - } else { - throw IncubedError.config(message: "Can not convert '\(val)' to int") - } - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for Double") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - -/// converts a RPC-Object to Bool or throws -internal func toBool(_ data:RPCObject?, _ optional:Bool = true) throws -> Bool?{ - if let data = data { - switch data { - case let .integer(val): - return val != 0; - case let .string(val): - if val == "true" || val=="0x1" { - return true - } else if val == "false" || val == "0x0" { - return false - } else { - throw IncubedError.config(message: "Invalid string to convert '\(val)' to Bool") - } - case let .bool(val): - return val - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for bool") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - -/// converts a RPC-Object to String or throws -internal func toString(_ data:RPCObject?, _ optional:Bool = true) throws -> String?{ - if let data = data { - switch data { - case let .integer(val): - return String(val) - case let .string(val): - return val - case let .bool(val): - return val ? "true":"false" - case .none: - if !optional { - throw IncubedError.config(message: "missing value") - } - return nil - default: - throw IncubedError.config(message: "Invalid type for String") - } - } else if !optional { - throw IncubedError.config(message: "missing value") - } - return nil -} - -/// converts a RPC-Object to a Dictory or throws -internal func toObject(_ data:RPCObject?,_ optional:Bool = true) throws -> [String: RPCObject]?{ - if let data = data { - switch data { - case let .dictionary(val): - return val - case .none: - return nil - default: - throw IncubedError.config(message: "Invalid type for Object") - } - } - return nil -} - - -/// converts a RPC-Object to a List or throws -internal func toArray(_ data:RPCObject?, _ optional:Bool = true) throws -> [RPCObject]?{ - if let data = data { - switch data { - case let .list(val): - return val - case .none: - return nil - default: - throw IncubedError.config(message: "Invalid type for Array") - } - } - return nil -} - -/// executes a rpc-request and converts the result as non optional. (will return a rejected promise if it is `nil`) -internal func execAndConvert(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { - let promise = Promise() - do { - try In3Request(method,params,in3,{ - switch $0 { - case let .error(msg): - promise.reject(with: IncubedError.rpc(message: msg)) - case let .success(data): - do { - if let v = try convertWith(data,false) { - promise.resolve(with: v) - } else { - promise.reject(with: IncubedError.rpc(message: "Null Value is not allowed here")) - } - } catch { - promise.reject(with: error) - } - } - }).exec() - } catch { - promise.reject(with: error) - } - return promise -} - -/// executes a rpc-request and converts the result as optional allowing `nil`as valid result. -internal func execAndConvertOptional(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) -> Future { - let promise = Promise() - do { - try In3Request(method,params,in3,{ - switch $0 { - case let .error(msg): - promise.reject(with: IncubedError.rpc(message: msg)) - case let .success(data): - do { - let val = try convertWith(data, true) - promise.resolve(with: val) - } catch { - promise.reject(with: error) - } - } - }).exec() - } catch { - promise.reject(with: error) - } - return promise -} - - - - -/// executes a rpc-request and converts the result as non optional. (will return a rejected promise if it is `nil`) -internal func execLocalAndConvert(in3:In3, method: String, params: RPCObject..., convertWith: @escaping (_ data:RPCObject?, _ optional:Bool) throws -> Type?) throws -> Type { - let res = try in3.execLocal(method, params) - return try convertWith(res,false)! -} diff --git a/swift/Sources/In3/Utils/Error.swift b/swift/Sources/In3/Utils/Error.swift deleted file mode 100644 index 054b4447a..000000000 --- a/swift/Sources/In3/Utils/Error.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation -/// Base Incubed errors -public enum IncubedError: Error { - - /// Configuration Error, which is only thrown within the Config or initializer of the In3 - case config(message: String) - - /// error during rpc-execution - case rpc(message: String) - - /// error during converting the response to a target - case convert(message: String) -} - -/// the result of a Transport operation. -/// it will only be used internally to report the time and http-status of the response, before verifying the result. -public enum TransportResult { - /// successful response - /// - Parameter data : the raw data - /// - Parameter time : the time in milliseconds to execute the request - case success(_ data:Data, _ time:Int) - - /// failed response - /// - Parameter msg : the error-message - /// - Parameter httpStatus : the http status code - case error(_ msg:String, _ httpStatus:Int) -} - -/// result of a RPC-Request -public enum RequestResult { - /// success full respons with the data as result. - case success(_ data:RPCObject) - - /// failed request with the msg describiung the error - case error(_ msg:String) -} diff --git a/swift/Sources/In3/Utils/JsonRpc.swift b/swift/Sources/In3/Utils/JsonRpc.swift deleted file mode 100644 index cd50f338a..000000000 --- a/swift/Sources/In3/Utils/JsonRpc.swift +++ /dev/null @@ -1,438 +0,0 @@ -import Foundation - -/* - spec from https://www.jsonrpc.org/specification - ----------------------------------------------- - Request object - A rpc call is represented by sending a Request object to a Server. The Request object has the following members: - jsonrpc - A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0". - method - A String containing the name of the method to be invoked. Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and MUST NOT be used for anything else. - params - A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted. - id - An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2] - The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. - [1] The use of Null as a value for the id member in a Request object is discouraged, because this specification uses a value of Null for Responses with an unknown id. Also, because JSON-RPC 1.0 uses an id value of Null for Notifications this could cause confusion in handling. - [2] Fractional parts may be problematic, since many decimal fractions cannot be represented exactly as binary fractions. - 4.1 Notification - A Notification is a Request object without an "id" member. A Request object that is a Notification signifies the Client's lack of interest in the corresponding Response object, and as such no Response object needs to be returned to the client. The Server MUST NOT reply to a Notification, including those that are within a batch request. - Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params","Internal error"). - 4.2 Parameter Structures - If present, parameters for the rpc call MUST be provided as a Structured value. Either by-position through an Array or by-name through an Object. - by-position: params MUST be an Array, containing the values in the Server expected order. - by-name: params MUST be an Object, with member names that match the Server expected parameter names. The absence of expected names MAY result in an error being generated. The names MUST match exactly, including case, to the method's expected parameters. - Response object - When a rpc call is made, the Server MUST reply with a Response, except for in the case of Notifications. The Response is expressed as a single JSON Object, with the following members: - jsonrpc - A String specifying the version of the JSON-RPC protocol. MUST be exactly "2.0". - result - This member is REQUIRED on success. - This member MUST NOT exist if there was an error invoking the method. - The value of this member is determined by the method invoked on the Server. - error - This member is REQUIRED on error. - This member MUST NOT exist if there was no error triggered during invocation. - The value for this member MUST be an Object as defined in section 5.1. - id - This member is REQUIRED. - It MUST be the same as the value of the id member in the Request Object. - If there was an error in detecting the id in the Request object (e.g. Parse error/Invalid Request), it MUST be Null. - Either the result member or error member MUST be included, but both members MUST NOT be included. - 5.1 Error object - When a rpc call encounters an error, the Response Object MUST contain the error member with a value that is a Object with the following members: - code - A Number that indicates the error type that occurred. - This MUST be an integer. - message - A String providing a short description of the error. - The message SHOULD be limited to a concise single sentence. - data - A Primitive or Structured value that contains additional information about the error. - This may be omitted. - The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.). - The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php - code message meaning - -32700 Parse error Invalid JSON was received by the server. - An error occurred on the server while parsing the JSON text. - -32600 Invalid Request The JSON sent is not a valid Request object. - -32601 Method not found The method does not exist / is not available. - -32602 Invalid params Invalid method parameter(s). - -32603 Internal error Internal JSON-RPC error. - -32000 to -32099 Server error Reserved for implementation-defined server-errors. - */ - -private let jsonrpcVersion = "2.0" - -internal struct JSONRequest: Codable { - var jsonrpc: String - var id: Int - var method: String - var params: JSONObject - - init(id: Int, method: String, params: JSONObject) { - self.jsonrpc = jsonrpcVersion - self.id = id - self.method = method - self.params = params - } -} - -internal struct JSONResponse: Codable { - var jsonrpc: String - var id: Int - var result: JSONObject? - var error: JSONError? - - init(id: Int, result: JSONObject) { - self.jsonrpc = jsonrpcVersion - self.id = id - self.result = result - self.error = nil - } - - init(id: Int, error: JSONError) { - self.jsonrpc = jsonrpcVersion - self.id = id - self.result = nil - self.error = error - } - - init(id: Int, errorCode: JSONErrorCode, error: Error) { - self.init(id: id, error: JSONError(code: errorCode, error: error)) - } - - init(id: Int, result: RPCObject) { - self.init(id: id, result: JSONObject(result)) - } - - init(id: Int, error: RPCError) { - self.init(id: id, error: JSONError(error)) - } -} - -internal struct JSONError: Codable { - var code: Int - var message: String - var data: Dictionary? - - init(code: Int, message: String) { - self.code = code - self.message = message - self.data = nil - } - - init(code: JSONErrorCode, message: String) { - self.init(code: code.rawValue, message: message) - } - - init(code: JSONErrorCode, error: Error) { - self.init(code: code, message: String(describing: error)) - } - - init(_ error: RPCError) { - switch error.kind { - case .invalidMethod: - self.init(code: .methodNotFound, message: error.description ?? "invalid method") - case .invalidParams: - self.init(code: .invalidParams, message: error.description ?? "invalid params") - case .invalidRequest: - self.init(code: .invalidRequest, message: error.description ?? "invalid request") - case .applicationError(let description): - self.init(code: .other, message: error.description ?? description) - } - } -} - -internal enum JSONErrorCode: Int, Codable { - case parseError = -32700 - case invalidRequest = -32600 - case methodNotFound = -32601 - case invalidParams = -32602 - case internalError = -32603 - case other = -32000 -} - -internal enum JSONObject: Codable { - case none - case string(String) - case integer(Int) - case double(Double) - case bool(Bool) - case list([JSONObject]) - case dictionary([String: JSONObject]) - - init(_ object: RPCObject) { - switch object { - case .none: - self = .none - case .string(let value): - self = .string(value) - case .integer(let value): - self = .integer(value) - case .double(let value): - self = .double(value) - case .bool(let value): - self = .bool(value) - case .list(let value): - self = .list(value.map { JSONObject($0) }) - case .dictionary(let value): - self = .dictionary(value.mapValues { JSONObject($0) }) - } - } -} - -internal extension JSONObject { - enum CodingKeys: CodingKey { - case string - case integer - case double - case bool - case list - case dictionary - } - - // FIXME: is there a more elegant way? - init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - do { - let value = try container.decode(String.self) - self = .string(value) - } catch { - do { - let value = try container.decode(Int.self) - self = .integer(value) - } catch { - do { - let value = try container.decode(Double.self) - self = .double(value) - } catch { - do { - let value = try container.decode(Bool.self) - self = .bool(value) - } catch { - do { - let value = try container.decode([JSONObject].self) - self = .list(value) - } catch { - do { - let value = try container.decode([String: JSONObject].self) - self = .dictionary(value) - } catch { - self = .none - } - } - } - } - } - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case .none: - break - case .string(let value): - try container.encode(value) - case .integer(let value): - try container.encode(value) - case .double(let value): - try container.encode(value) - case .bool(let value): - try container.encode(value) - case .list(let value): - try container.encode(value) - case .dictionary(let value): - try container.encode(value) - } - } -} - -/// Wrapper enum for a rpc-object, which could be different kinds -public enum RPCObject: Equatable { - /// a JSON `null` value. - case none - - /// a String value - case string(String) - - /// a Integer - case integer(Int) - - /// a Doucle-Value - case double(Double) - - /// a Boolean - case bool(Bool) - - /// a Array or List of RPC-Objects - case list([RPCObject]) - - /// a JSON-Object represented as Dictionary with properties as keys and their values as RPCObjects - case dictionary([String: RPCObject]) - - /// Wrap a String as Value - public init(_ value: AnyObject) { - switch value { - case let val as UInt64: - self = .integer(Int(val)) - case let val as Int: - self = .integer(val) - case let val as Double: - self = .double(val) - case let val as String: - self = .string(val) - case let val as Bool: - self = .bool(val) - case nil: - self = .none - case let val as [AnyObject]: - self = .list(val.map { RPCObject($0) }) - case let val as [String]: - self = .list(val.map { RPCObject($0) }) - case let val as [String:AnyObject]: - self = .dictionary(val.mapValues({ RPCObject($0) })) - default: - self = .none - } - } - - /// Wrap a String as Value - public init(_ array: [AnyObject]) { - self = .list(array.map({ RPCObject($0)})) - } - - /// Wrap a String as Value - public init(_ value: String) { - self = .string(value) - } - - - /// Wrap a Integer as Value - public init(_ value: Int) { - self = .integer(value) - } - - /// Wrap a Integer as Value - public init(_ value: UInt64) { - self = .integer(Int(value)) - } - - /// Wrap a UInt256 as Value - public init(_ value: UInt256) { - self = .string("0x" + value.toString(radix: 16)) - } - - /// Wrap a Double as Value - public init(_ value: Double) { - self = .double(value) - } - - /// Wrap a Bool as Value - public init(_ value: Bool) { - self = .bool(value) - } - - /// Wrap a String -Array as Value - public init(_ value: [String]) { - self = .list(value.map { RPCObject($0) }) - } - - /// Wrap a String -Array as Value - public init(_ value: [String?]) { - self = .list(value.map { $0 == nil ? RPCObject.none : RPCObject($0!) }) - } - - /// Wrap a Integer -Array as Value - public init(_ value: [Int]) { - self = .list(value.map { RPCObject($0) }) - } - - /// Wrap a Object with String values as Value - public init(_ value: [String: String]) { - self = .dictionary(value.mapValues { RPCObject($0) }) - } - - /// Wrap a Object with Integer values as Value - public init(_ value: [String: Int]) { - self = .dictionary(value.mapValues { RPCObject($0) }) - } - - /// Wrap a Object with RPCObject values as Value - public init(_ value: [String: RPCObject]) { - self = .dictionary(value) - } - - /// Wrap a Array or List of RPCObjects as Value - public init(_ value: [RPCObject]) { - self = .list(value) - } - - internal init(_ object: JSONObject) { - switch object { - case .none: - self = .none - case .string(let value): - self = .string(value) - case .integer(let value): - self = .integer(value) - case .double(let value): - self = .double(value) - case .bool(let value): - self = .bool(value) - case .list(let value): - self = .list(value.map { RPCObject($0) }) - case .dictionary(let value): - self = .dictionary(value.mapValues { RPCObject($0) }) - } - } - - public func asObject() -> T { - switch self { - case .none: - return 0 as! T - case .integer( let val): - return val as! T - case .string( let val): - return val as! T - case .double(let val): - return val as! T - case .bool( let val): - return val as! T - case .list( let val): - return val.map({(src:RPCObject) -> T in src.asObject() }) as! T - case .dictionary(let val): - return val.mapValues({(src:RPCObject) -> T in src.asObject() }) as! T - } - } -} - -/// Error of a RPC-Request -public struct RPCError { - /// initializer - public init(_ kind: Kind, description: String? = nil) { - self.kind = kind - self.description = description - } - - /// the error-type - public let kind: Kind - - /// the error description - public let description: String? - - /// the error type - public enum Kind { - /// invalid Method - case invalidMethod - /// invalid Params - case invalidParams(String) - /// invalid Request - case invalidRequest(String) - /// application Error - case applicationError(String) - } -} - diff --git a/swift/Sources/In3/Utils/Promise.swift b/swift/Sources/In3/Utils/Promise.swift deleted file mode 100644 index 284393b3b..000000000 --- a/swift/Sources/In3/Utils/Promise.swift +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Swift by Sundell sample code - * Copyright (c) John Sundell 2020 - * See LICENSE file for license - * - * Read the article at https://swiftbysundell.com/posts/under-the-hood-of-futures-and-promises-in-swift - */ - -import Foundation - - -public class Future { - public typealias Result = Swift.Result - - fileprivate var result: Result? { - // Observe whenever a result is assigned, and report it: - didSet { result.map(report) } - } - private var callbacks = [(Result) -> Void]() - - public func observe(using callback: @escaping (Result) -> Void) { - // If a result has already been set, call the callback directly: - if let result = result { - return callback(result) - } - - callbacks.append(callback) - } - - private func report(result: Result) { - callbacks.forEach { $0(result) } - callbacks = [] - } -} - -public class Promise: Future { - init(value: Value? = nil) { - super.init() - - // If the value was already known at the time the promise - // was constructed, we can report it directly: - result = value.map(Result.success) - } - - public func resolve(with value: Value) { - result = .success(value) - } - - public func reject(with error: Error) { - result = .failure(error) - } -} - -extension Future { - func chained( - using closure: @escaping (Value) throws -> Future - ) -> Future { - // We'll start by constructing a "wrapper" promise that will be - // returned from this method: - let promise = Promise() - - // Observe the current future: - observe { result in - switch result { - case .success(let value): - do { - // Attempt to construct a new future using the value - // returned from the first one: - let future = try closure(value) - - // Observe the "nested" future, and once it - // completes, resolve/reject the "wrapper" future: - future.observe { result in - switch result { - case .success(let value): - promise.resolve(with: value) - case .failure(let error): - promise.reject(with: error) - } - } - } catch { - promise.reject(with: error) - } - case .failure(let error): - promise.reject(with: error) - } - } - - return promise - } -} - -extension Future { - func transformed( - with closure: @escaping (Value) throws -> T - ) -> Future { - chained { value in - try Promise(value: closure(value)) - } - } -} - -extension Future where Value == Data { - func decoded( - as type: T.Type = T.self, - using decoder: JSONDecoder = .init() - ) -> Future { - transformed { data in - try decoder.decode(T.self, from: data) - } - } -} diff --git a/swift/Sources/In3/Utils/Transport.swift b/swift/Sources/In3/Utils/Transport.swift deleted file mode 100644 index 2610890b9..000000000 --- a/swift/Sources/In3/Utils/Transport.swift +++ /dev/null @@ -1,222 +0,0 @@ -import Foundation -import CIn3 - -internal func httpTransfer(_ surl: String, _ method:String, _ payload:Data?, _ headers: [String], cb:@escaping (_ data:TransportResult)->Void) { - - guard let url = URL(string:surl) else { - DispatchQueue.main.async { - cb(TransportResult.error("no valid url :"+surl,-7)) - } - return - } - - if let pl = payload { - print("Request to " , url," payload :"+String(decoding: pl, as: UTF8.self)) - } - - let reqStart = Date() - var request = URLRequest(url: url) - request.httpMethod = method - request.httpBody = payload - if method == "POST" { - request.addValue("application/json", forHTTPHeaderField: "Content-Type") - request.addValue("application/json", forHTTPHeaderField: "Accept") - } - for h in headers { - let tokens:[String] = h.split(separator: ":", maxSplits: 2).map { String($0).trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) } - if tokens.count == 2 { - request.addValue(tokens[1], forHTTPHeaderField: tokens[0]) - } - } - URLSession.shared.dataTask(with: request,completionHandler: { data, response, error in - - if let err = error { - DispatchQueue.main.async { - cb(TransportResult.error("Could not send request : \(err)", 500)) - } - return - } - guard let resp = response as? HTTPURLResponse else { - DispatchQueue.main.async { - cb(TransportResult.error("Invalid response", 500)) - } - return - } - guard let d = data else { - DispatchQueue.main.async { - cb(TransportResult.error("No data", 500)) - } - return - } - print("Response : " , String(decoding: d, as: UTF8.self)) - - if resp.statusCode < 400 && resp.statusCode >= 200 { - DispatchQueue.main.async { - cb(TransportResult.success(d, Int(Date().timeIntervalSince(reqStart)*1000))) - } - } else { - DispatchQueue.main.async { - cb(TransportResult.error("Invalid Status :\(resp.statusCode)", resp.statusCode)) - } - } - }).resume() -} - - -internal class In3Request { - var req:UnsafeMutablePointer - var in3:In3 - var cb: (_ result:RequestResult)->Void - var freed: Bool - - init(_ method: String, _ params: [RPCObject],_ _in3:In3, _ _cb: @escaping (_ result:RequestResult)->Void) throws { - let r = req_new_clone(_in3.in3, String(decoding: try JSONEncoder().encode(JSONRequest(id: 1, method: method, params: JSONObject(RPCObject(params)))), as: UTF8.self)) - if let r = r { - req = r - } - else { - throw IncubedError.rpc(message: "Invalid JSON") - } - in3 = _in3 - cb = _cb - freed = false - } - - func free() { - if !freed { - freed = true - req_free(req) - } - } - - deinit { - self.free() - } - - func reportError(req:UnsafeMutablePointer) { - if let error = req.pointee.error { - DispatchQueue.main.async { - self.cb(RequestResult.error(String(cString: error))) - } - self.free() - } - else if let required = req.pointee.required { - reportError(req: required) - } - else { - DispatchQueue.main.async { - self.cb(RequestResult.error("Unknown Error")) - } - self.free() - } - } - - func exec() { - switch in3_req_exec_state(req) { - case REQ_SUCCESS : - let result = req_get_result_json(req,0) - if let res = result { - let resultString = String(cString: res) - do { - let response = try JSONDecoder().decode(JSONObject.self, from: resultString.data(using: .utf8)!) - DispatchQueue.main.async { - self.cb(RequestResult.success(RPCObject(response))) - } - } catch { - DispatchQueue.main.async { - self.cb(RequestResult.error( "Error parsing the result '\(resultString)' : \(error)")) - } - } - } else { - DispatchQueue.main.async { - self.cb(RequestResult.error( "The response was null")) - } - } - - _free_(result) - self.free() - - case REQ_ERROR : - reportError(req: req) - - - case REQ_WAITING_TO_SEND: - // create request - let http_req = in3_create_request(req) - guard let http = http_req else { - reportError(req: req) - return - } - let req_ptr = http.pointee.req - guard let req = req_ptr else { - reportError(req: self.req) - return - } - - for i in 0.. Void in - // in case the response is not needed, we simply discard it. - if self.freed || in3_req_state(req) != REQ_WAITING_FOR_RESPONSE { - return - } - - // set the response... - switch res { - case let .success(data, time): - data.withUnsafeBytes { - in3_ctx_add_response(req,Int32(i),0,$0.baseAddress?.assumingMemoryBound(to: Int8.self),Int32(data.count), UInt32(time)) - } - case let .error(msg,httpStatus): - msg.data(using: .utf8)!.withUnsafeBytes { - in3_ctx_add_response(req,Int32(i),Int32(-httpStatus),$0.baseAddress?.assumingMemoryBound(to: Int8.self),Int32(-1), UInt32(0)) - } - } - // now try to verify the response - self.exec() - } - - // do we need to wait before sending the request? - if http.pointee.wait > 0 { - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Int(http.pointee.wait)) ) { - self.sendHttp(http: http, index:i, cb:cbResult) - } - } else { - self.sendHttp(http: http, index:i, cb: cbResult) - } - } - - case REQ_WAITING_FOR_RESPONSE: - // here we do nothing, but simply wait for the next event - return - default: - DispatchQueue.main.async { - self.cb(RequestResult.error( "not expected")) - } - } - } - - func sendHttp(http:UnsafeMutablePointer, index:Int, cb:@escaping (_ data:TransportResult)->Void) { - let payload:Data? = http.pointee.payload_len == 0 ? nil : Data(buffer:UnsafeMutableBufferPointer(start: http.pointee.payload, count: Int(http.pointee.payload_len))) - var headers:[String] = [] - var p = http.pointee.headers - let url = http.pointee.urls + index - while let ph = p { - headers.append(String(cString: ph.pointee.value)) - p = ph.pointee.next - } - if let url = url.pointee { - in3.transport( String(cString:url) , String(cString: http.pointee.method), payload, headers, cb) - } else { - DispatchQueue.main.async { - cb(TransportResult.error("No URL specified",500)) - } - } - - // if this was the last request we sent out, we clean up the request. - if index == http.pointee.urls_len - 1 { - request_free(http) - } - } - - -} diff --git a/swift/Sources/In3/Utils/UInt256.swift b/swift/Sources/In3/Utils/UInt256.swift deleted file mode 100644 index d296f86ef..000000000 --- a/swift/Sources/In3/Utils/UInt256.swift +++ /dev/null @@ -1,229 +0,0 @@ -import CIn3 -import Foundation - - -extension mp_int { - init() { - self = mp_int(used: 0, alloc: 0, sign: 0, dp: nil) - } -} -/// a bigint implementation based on tommath to represent big numbers -/// It is used to represent uint256 values -final public class UInt256: CustomStringConvertible, Hashable, Comparable, Decodable, Encodable { - var value = mp_int() - - /// creates a empt (0)-value - public init() { - mp_init_set(&self.value, 0) - } - - /// i nitializes its value from a uint64 type - public init(_ v:UInt64) { - mp_init_set(&self.value, v) - } - - /// inits its value from a Int - public required convenience init(_ val: IntegerLiteralType) { - self.init(UInt64(val)) - } - - - /// copies the value from another UInt256 - public init(_ value: UInt256) { - mp_init_copy(&self.value, &value.value) - } - - /// initialze the value from a string. - /// if the string starts with '0x' it will interpreted as radix 16 - /// otherwise the default for the radix is 10 - /// - Parameter radix : the radix or the base to use when parsing the String (10 - decimal, 16 - hex, 2 - binary ... ) - public init?(_ val: String, radix: Int = 10) { - var r = radix - var v = val - assert(r >= 2 && r <= 36, "Only radix from 2 to 36 are supported") - - if v.starts(with: "0x") { - v = String(v.suffix(from: v.index(v.startIndex, offsetBy: 2))) - r = 16 - } - - if mp_read_radix(&self.value, v, Int32(r)) != 0 { - return nil - } - } - - /// initializes from a decoder - public init(from decoder: Decoder) throws { - let v = try decoder.singleValueContainer().decode(String.self) - if v.starts(with: "0x") { - if mp_read_radix(&self.value, String(v.suffix(from: v.index(v.startIndex, offsetBy: 2))), Int32(16)) != 0 { - throw IncubedError.convert(message: "Invalid UInt256 values") - } - } else { - throw IncubedError.convert(message: "UInt256 value must start with '0x'") - } - } - - /// encodes the value to a decoder - public func encode(to encoder: Encoder) throws { - var c = encoder.singleValueContainer() - try c.encode(self.hexValue) - } - - - /// hash of the value - public func hash(into hasher: inout Hasher) { - toString(radix: 16).hash(into: &hasher) - } - - /// cleanup freeing the value - deinit { - mp_clear(&self.value); - } - - /// returns the value as Double (as close as possible) - public var doubleValue: Double { - return mp_get_double(&self.value) - } - - /// the hex representation staring with '0x' - public var hexValue: String { - return "0x" + self.toString(radix: 16) - } - - /// a unsigned Int representation (if possible) - public var uintValue: UInt { - return mp_get_int(&self.value) - } - - /// a unsigned UInt64 representation (if possible) - public var uint64Value: UInt64 { - return mp_get_long_long(&self.value) - } - - /// a string representation based on the given radix. - /// - Parameter radix : the radix or the base to use when parsing the String (10 - decimal, 16 - hex, 2 - binary ... ) - public func toString(radix: Int = 10) -> String { - assert(radix >= 2 && radix <= 36, "invalid radix") - - var len = Int32() - mp_radix_size(&self.value, Int32(radix), &len) - - var buf = [Int8]( repeating: 0, count: Int(len+1)) - mp_toradix(&self.value, &buf, Int32(radix)) - return String(cString: buf).lowercased() - } - - /// String representation as decimals - public var description: String { - return toString(radix: 10) - } - - /// compare 2 UInt256 values - /// the result is zero if they are equal - /// negative if the current value is smaller than the given - /// positive if the current value is higher than the given - public func compare(other: UInt256) -> Int32 { - return mp_cmp(&self.value, &other.value) - } - - /// adds the given number and returns the sum of both - public func add(_ val:UInt256) -> UInt256 { - let res:UInt256 = UInt256() - mp_add(&self.value, &val.value, &res.value) - return res - } - - /// substracts the given number and returns the difference of both - public func sub(_ val:UInt256) -> UInt256 { - let res:UInt256 = UInt256() - mp_sub(&self.value, &val.value, &res.value) - return res - } - - /// multiplies the current with the given number and returns the product of both - public func mul(_ val:UInt256) -> UInt256 { - let res:UInt256 = UInt256() - mp_mul(&self.value, &val.value, &res.value) - return res - } - - /// divides the current number by the given and return the result - public func div(_ val:UInt256) -> UInt256 { - let res:UInt256 = UInt256() - let mod:UInt256 = UInt256() - mp_div(&self.value, &val.value, &res.value, &mod.value) - return res - } - - /// divides the current number by the given and return the rest or module operator - public func mod(_ val:UInt256) -> UInt256 { - let res:UInt256 = UInt256() - mp_mod(&self.value, &val.value, &res.value) - return res - } -} - -public func == (a: UInt256, b: UInt256) -> Bool { - return a.compare(other: b) == MP_EQ -} - -public func < (a: UInt256, b: UInt256) -> Bool { - return a.compare(other: b) == MP_LT -} - -public func > (a: UInt256, b: UInt256) -> Bool { - return a.compare(other: b) == MP_GT -} - -public func >= (a: UInt256, b: UInt256) -> Bool { - return a.compare(other: b) != MP_LT -} - -public func <= (a: UInt256, b: UInt256) -> Bool { - return a.compare(other: b) != MP_GT -} - -public func + (a: UInt256, b: UInt256) -> UInt256 { - return a.add(b) -} - -public func + (a: UInt256, b: Int) -> UInt256 { - return b < 0 ? a.sub(UInt256(-b)) : a.add(UInt256(b)) -} - -public func + (a: UInt256, b: UInt64) -> UInt256 { - return a.add(UInt256(b)) -} - -public func - (a: UInt256, b: UInt256) -> UInt256 { - return a.sub(b) -} - -public func - (a: UInt256, b: Int) -> UInt256 { - return b >= 0 ? a.sub(UInt256(b)) : a.add(UInt256(-b)) -} - -public func - (a: UInt256, b: UInt64) -> UInt256 { - return a.sub(UInt256(b)) -} - -public func / (a: UInt256, b: UInt256) -> UInt256 { - return a.div(b) -} - -public func * (a: UInt256, b: UInt256) -> UInt256 { - return a.mul(b) -} - -public func % (a: UInt256, b: UInt256) -> UInt256 { - return a.mod(b) -} - - -extension UInt64 { - init(_ val:UInt256) { - self = val.uint64Value - } -} - diff --git a/swift/Tests/In3Tests/In3Tests.swift b/swift/Tests/In3Tests/In3Tests.swift deleted file mode 100644 index 14555e4a7..000000000 --- a/swift/Tests/In3Tests/In3Tests.swift +++ /dev/null @@ -1,107 +0,0 @@ -import XCTest -import Foundation -@testable import In3 - -final class In3Tests: XCTestCase { - - func testUInt256() throws { - let val: UInt256 = UInt256(65535) - XCTAssertEqual(val.description,"65535") - XCTAssertEqual(val.uint64Value,UInt64(65535)) - XCTAssertEqual(val.toString(radix: 16),"ffff") - let r = val + UInt256(1) - XCTAssertEqual(r.description,"65536") - if let v = UInt256("0xffff") { - XCTAssertEqual(v.description,"65535") - } - else { - XCTFail("Could not parse UINt256") - } - if let v = UInt256("0x1") { - XCTAssertEqual(v.description,"1") - XCTAssertEqual(v.hexValue,"0x1") - } else { - XCTFail("Could not parse UINt256") - } - if let v = UInt256("0x0") { - XCTAssertEqual(v.description,"0") - XCTAssertEqual(v.hexValue,"0x0") - } else { - XCTFail("Could not parse UINt256") - } - - let a = UInt256(20) - let b = a + 10 - XCTAssertEqual(b.uintValue,30) - - - } - - func testLocal() throws { - let in3 = try In3(In3Config(chainId: "mainnet")) - let hash = try in3.execLocal("keccak",RPCObject("simon")) - switch hash { - case let .string(value): - XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") - default: - XCTFail("Invalid return type") - } - } - - func testJSON() throws { - let in3 = try In3(In3Config(chainId: "mainnet")) - let res = in3.executeJSON("{\"method\":\"keccak\",\"params\":[\"simon\"]}") - XCTAssertEqual(res , "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":\"0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a\"}") - } - - func testExec() throws { - let expect = XCTestExpectation(description: "Should get a hash-value") - let in3 = try In3(In3Config(chainId: "mainnet")) - try in3.exec("keccak", RPCObject("simon"), cb: { - switch $0 { - case let .error(msg): - XCTFail(msg) - case let .success(hash): - switch hash { - case let .string(value): - XCTAssertEqual(value , "0x12c66c32d34a85291ac705641fb4d8cdf784dd6f84ecec01170f8d0735d54a4a") - expect.fulfill() - default: - XCTFail("Invalid return type") - } - - } - }) - wait(for: [expect], timeout: 1000) - } - - func testAPI() throws { - let expect = XCTestExpectation(description: "Should get a hash-value") -// let in3 = try In3(Config(rpc: "https://rpc.slock.it/mainnet")) - let in3 = try In3(In3Config(chainId: "mainnet")) - let eth = Eth(in3) - eth.getBlock().observe(using: { - switch $0 { - case let .failure(err): - print(err.localizedDescription) - case let .success( val ): - if let b = val { - print("block : ",b.miner) - } else { - print("on tx found ") - } - expect.fulfill() - } - }) - wait(for: [expect], timeout: 10) - - } - - - static var allTests = [ - ("UInt256", testUInt256), - ("execlocal", testLocal), - ("execJSON", testJSON), - ("exec", testExec), - ] -} diff --git a/swift/Tests/In3Tests/Mock.swift b/swift/Tests/In3Tests/Mock.swift deleted file mode 100644 index 78015b0a2..000000000 --- a/swift/Tests/In3Tests/Mock.swift +++ /dev/null @@ -1,10 +0,0 @@ - -import XCTest -import Foundation -import In3 - -internal func createIn3(mockdata:[String:String]) throws -> In3 { -// let in1 = try In3(In3Config(chainId: "mainnet")) - let in3 = try In3Config(chainId: "mainnet").createClient() - return in3 -} diff --git a/swift/Tests/In3Tests/XCTestManifests.swift b/swift/Tests/In3Tests/XCTestManifests.swift deleted file mode 100644 index 1b5c3d87c..000000000 --- a/swift/Tests/In3Tests/XCTestManifests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import XCTest - -#if !canImport(ObjectiveC) -public func allTests() -> [XCTestCaseEntry] { - return [ - testCase(In3Tests.allTests), - ] -} -#endif diff --git a/swift/Tests/LinuxMain.swift b/swift/Tests/LinuxMain.swift deleted file mode 100644 index 85e300a77..000000000 --- a/swift/Tests/LinuxMain.swift +++ /dev/null @@ -1,7 +0,0 @@ -import XCTest - -import In3Tests - -var tests = [XCTestCaseEntry]() -tests += In3Tests.allTests() -XCTMain(tests) diff --git a/swift/ci.yml b/swift/ci.yml deleted file mode 100644 index 7c2120cd0..000000000 --- a/swift/ci.yml +++ /dev/null @@ -1,36 +0,0 @@ -.only_swift: - needs: [] - rules: - - changes: - - swift/**/* - - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+-(alpha|beta|rc)\.[0-9]+$/' - - if: '$CI_COMMIT_REF_NAME == "master"' - - if: '$CI_COMMIT_REF_NAME == "develop"' - - if: '$CI_COMMIT_REF_PROTECTED == "true"' - -.only_deploy: - rules: - - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/' - when: manual - - - -swift: - stage: bindings - needs: [] - tags: - - mac-os - script: - - mkdir build - - cd build - - MACOSX_DEPLOYMENT_TARGET=10.15 cmake -DCMAKE_BUILD_TYPE=release -DSWIFT=true .. && make - - cd ../swift - - swift build - - swift test 2> output - - cat output - - ../scripts/create_swift_junit.js < output >swift.xml - artifacts: - reports: - junit: swift/swift.xml - paths: - - swift/.build diff --git a/swift/docs/1_intro.md b/swift/docs/1_intro.md deleted file mode 100644 index 717f44fd3..000000000 --- a/swift/docs/1_intro.md +++ /dev/null @@ -1,33 +0,0 @@ -# API Reference Swift - -The swift binding contains binaries are only available for macos and ios. ( for now) - -## Install - - -TODO - -## Usage - -In order to use incubed, you need to add the In3-Package as dependency and import into your code: - -```swift -import In3 - -// configure and create a client. -let in3 = try In3Config(chainId: "mainnet", requestCount:1).createClient() - -// use the Eth-Api to execute requests -Eth(in3).getTransactionReceipt(hash: "0xe3f6f3a73bccd73b77a7b9e9096fe07b9341e7d1d8f1ad8b8e5207f2fe349fa0").observe(using: { - switch $0 { - case let .failure(err): - print("Failed to get the tx : \(err)") - case let .success( tx ): - if let tx = tx { - print("Found tx with txhash \(tx.hash)") - } else { - print("Tx does not exist") - } - } - }) -``` From 66c1733efef9a924f750ab2b2e65aa6179e5edb9 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 15 Apr 2021 12:07:26 +0200 Subject: [PATCH 129/221] move ci-scripts --- .gitlab-ci.yml | 2 +- .../code-quality.gitlab-ci.yml | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename code-quality.gitlab-ci.yml => .gitlab/code-quality.gitlab-ci.yml (100%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 29a522853..50c52ceaa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,7 +38,7 @@ stages: # all the CI files to include and run, they are imported before the CI is started include: - - local: "code-quality.gitlab-ci.yml" + - local: "/.gitlab/code-quality.gitlab-ci.yml" - local: "/c/ci.yml" - local: "/c/ci-analyse.yml" - local: "/c/ci-deploy.yml" diff --git a/code-quality.gitlab-ci.yml b/.gitlab/code-quality.gitlab-ci.yml similarity index 100% rename from code-quality.gitlab-ci.yml rename to .gitlab/code-quality.gitlab-ci.yml From 4d4cfadec67780fdc14272af55e4124fc2b8e879 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 15 Apr 2021 19:29:59 +0200 Subject: [PATCH 130/221] export options to include --- CMakeLists.txt | 249 +--------------------------------------------- c/options.cmake | 257 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+), 248 deletions(-) create mode 100644 c/options.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a6145a77..b14c2f810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,262 +38,15 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/scripts/cmake_mo # project name project(in3) -# options -option(BUILD_DOC "generates the documenation with doxygen." OFF) -option(TAG_VERSION "the tagged version, which should be used" 3.0.0) -option(ETH_NANO "build minimal eth verification.(eth_getTransactionReceipt)" ON) -option(ETH_BASIC "build basic eth verification.(all rpc-calls except eth_call)" ON) -option(ETH_FULL "build full eth verification.(including eth_call)" ON) -option(IPFS "build IPFS verification" ON) -option(COLOR "Enable color codes for debug" ON) -option(BTC "if true, the bitcoin verifiers will be build" ON) -option(IN3API "build the USN-API which offer better interfaces and additional functions on top of the pure verification" ON) -option(USE_PRECOMPUTED_EC "if true the secp256k1 curve uses precompiled tables to boost performance. turning this off makes ecrecover slower, but saves about 37kb." ON) -option(LOGGING "if set logging and human readable error messages will be inculded in th executable, otherwise only the error code is used. (saves about 19kB)" ON) -option(EVM_GAS "if true the gas costs are verified when validating a eth_call. This is a optimization since most calls are only interessted in the result. EVM_GAS would be required if the contract uses gas-dependend op-codes." true) -option(IN3_LIB "if true a shared anmd static library with all in3-modules will be build." ON) -option(TEST "builds the tests and also adds special memory-management, which detects memory leaks, but will cause slower performance" OFF) -option(FAST_MATH "Math optimizations used in the EVM. This will also increase the filesize." OFF) -option(SEGGER_RTT "Use the segger real time transfer terminal as the logging mechanism" OFF) -option(CURL_BLOCKING "if true the curl-request will block until the response is received" OFF) -option(JAVA "build the java-binding (shared-lib and jar-file)" OFF) -option(JAVA_MULTI_LIBS "embedds multiple shared libs in the jar" OFF) -option(WASM "Includes the WASM-Build. In order to build it you need emscripten as toolchain. Usually you also want to turn off other builds in this case." OFF) -option(ASMJS "compiles the code as asm.js." OFF) -option(WASM_EMBED "embedds the wasm as base64-encoded into the js-file" ON) -option(WASM_EMMALLOC "use ther smaller EMSCRIPTEN Malloc, which reduces the size about 10k, but may be a bit slower" ON) -option(WASM_SYNC "intiaializes the WASM synchronisly, which allows to require and use it the same function, but this will not be supported by chrome (4k limit)" OFF) -option(CODE_COVERAGE "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" OFF) -option(GCC_ANALYZER "GCC10 static code analyses" OFF) -option(PAY_ETH "support for direct Eth-Payment" OFF) -option(USE_SCRYPT "integrate scrypt into the build in order to allow decrypt_key for scrypt encoded keys." ON) -option(USE_CURL "if true the curl transport will be built (with a dependency to libcurl)" ON) -option(USE_WINHTTP "if true the winhttp transport will be built (with a dependency to winhttp)" OFF) -option(LEDGER_NANO "include support for nano ledger" OFF) -option(ESP_IDF "include support for ESP-IDF microcontroller framework" OFF) -option(ASSERTIONS "includes assertions into the code, which help track errors but may cost time during runtime" OFF) -OPTION(TRANSPORTS "builds transports, which may require extra libraries." ON) -OPTION(IN3_SERVER "support for proxy server as part of the cmd-tool, which allows to start the cmd-tool with the -p option and listens to the given port for rpc-requests" OFF) -OPTION(CMD "build the comandline utils" ON) -OPTION(RECORDER "enable recording option for reproduce executions" ON) -OPTION(POA "support POA verification including validatorlist updates" OFF) -OPTION(MULTISIG "add capapbility to sign with a multig. Currrently only gnosis safe is supported" ON) -OPTION(ZKSYNC "add RPC-function to handle zksync-payments" ON) -OPTION(ZKCRYPTO_LIB "Path to the static zkcrypto-lib" OFF) -OPTION(SENTRY "Enable Sentry" OFF) -OPTION(BTC_PRE_BPI34 "Enable BTC-Verfification for blocks before BIP34 was activated" ON) -OPTION(PK_SIGNER "Enable Signing with private keys" ON) -OPTION(NODESELECT_DEF "Enable default nodeselect implementation" ON) -OPTION(NODESELECT_DEF_WL "Enable default nodeselect whitelist implementation" ON) -OPTION(PLGN_CLIENT_DATA "Enable client-data plugin" OFF) -OPTION(THREADSAFE "uses mutex to protect shared nodelist access" ON) -OPTION(SWIFT "swift API for swift bindings" OFF) - - -IF (DEFINED ANDROID_ABI) - set(TRANSPORTS,false) - set(IN3_LIB,false) - set(USE_CURL,off) - set(CMD,false) - set(JAVA,true) - set(RECORDER,false) -ENDIF() -IF (SWIFT) - set(TRANSPORTS,false) - set(IN3_LIB,true) - set(USE_CURL, false) - set(CMD,false) - set(JAVA,false) - set(RECORDER,false) -ENDIF() - -IF (BTC_PRE_BPI34) - ADD_DEFINITIONS(-DBTC_PRE_BPI34) -ENDIF (BTC_PRE_BPI34) - -IF (POA) - ADD_DEFINITIONS(-DPOA) -ENDIF (POA) - -IF (PK_SIGNER) - ADD_DEFINITIONS(-DPK_SIGNER) - set(IN3_API ${IN3_API} pk_signer) -ENDIF (PK_SIGNER) - -if (USE_PRECOMPUTED_EC) - ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=1) -else() - ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=0) -endif() - -if (LOGGING) - ADD_DEFINITIONS(-DLOGGING) -endif() - -if (MULTISIG) - ADD_DEFINITIONS(-DMULTISIG) -endif() - -if (ZKSYNC) - ADD_DEFINITIONS(-DZKSYNC) - set(WASM_MODULES ${WASM_MODULES} zksync) - set(IN3_API ${IN3_API} zksync) -endif() - - -if(ETH_FULL) - ADD_DEFINITIONS(-DETH_FULL) - set(IN3_VERIFIER eth_full) - set(ETH_BASIC true) - set(ETH_NANO true) -elseif(ETH_BASIC) - ADD_DEFINITIONS(-DETH_BASIC) - set(IN3_VERIFIER eth_basic) - set(ETH_NANO true) -elseif(ETH_NANO) - ADD_DEFINITIONS(-DETH_NANO) - set(IN3_VERIFIER eth_nano) -endif() - -if (ETH_NANO) - set(WASM_MODULES ${WASM_MODULES} eth) -endif() - -if(IN3API) - ADD_DEFINITIONS(-DETH_API) - set(IN3_API ${IN3_API} eth_api) -endif() - -if (ESP_IDF) - ADD_DEFINITIONS(-DESP_IDF) -endif() - -if(PAY_ETH) - ADD_DEFINITIONS(-DPAY_ETH -DPAY) - set(IN3_API ${IN3_API} pay_eth) -endif() - -if(IPFS) - ADD_DEFINITIONS(-DIPFS) - set(IN3_VERIFIER ${IN3_VERIFIER} ipfs) - set(WASM_MODULES ${WASM_MODULES} ipfs) - - if(IN3API) - set(IN3_API ${IN3_API} ipfs_api) - endif() -endif() - -if(BTC) - ADD_DEFINITIONS(-DBTC) - set(IN3_VERIFIER ${IN3_VERIFIER} btc) - set(WASM_MODULES ${WASM_MODULES} btc) - if(IN3API) - set(IN3_API ${IN3_API} btc_api) - endif() -endif() - -if(LEDGER_NANO) - add_definitions(-DLEDGER_NANO) -endif() - -if(COLOR AND NOT (MSVC OR MSYS OR MINGW)) - ADD_DEFINITIONS(-DLOG_USE_COLOR) -endif() - - -if(CMAKE_BUILD_TYPE MATCHES Debug) - ADD_DEFINITIONS(-DDEBUG) -endif(CMAKE_BUILD_TYPE MATCHES Debug) - -if(EVM_GAS) - ADD_DEFINITIONS(-DEVM_GAS) -endif(EVM_GAS) - -if(FAST_MATH) - ADD_DEFINITIONS(-DIN3_MATH_FAST) -else() - ADD_DEFINITIONS(-DIN3_MATH_LITE) -endif(FAST_MATH) - -if(SEGGER_RTT) - ADD_DEFINITIONS(-DSEGGER_RTT) -endif(SEGGER_RTT) - -if(RECORDER) - ADD_DEFINITIONS(-DRECORDER) -endif(RECORDER) - -if (SENTRY) - ADD_DEFINITIONS(-DSENTRY) - set(IN3_API ${IN3_API} in3_sentry) -endif() - -if (NODESELECT_DEF) - ADD_DEFINITIONS(-DNODESELECT_DEF) - if (NODESELECT_DEF_WL) - ADD_DEFINITIONS(-DNODESELECT_DEF_WL) - endif() - set(IN3_NODESELECT ${IN3_NODESELECT} nodeselect_def) -endif() - -# handle version -if (TAG_VERSION) - set(PROJECT_VERSION "${TAG_VERSION}") -else(TAG_VERSION) - set(PROJECT_VERSION "3.0.0-local") -endif(TAG_VERSION) - -MESSAGE(STATUS "Building version ${PROJECT_VERSION}") - -string(REPLACE "." ";" VERSION_LIST ${PROJECT_VERSION}) -list(GET VERSION_LIST 0 PROJECT_VERSION_MAJOR) -list(GET VERSION_LIST 1 PROJECT_VERSION_MINOR) -list(GET VERSION_LIST 2 PROJECT_VERSION_PATCH) - -ADD_DEFINITIONS("-DIN3_VERSION=\"${PROJECT_VERSION}\"") -ADD_DEFINITIONS(-DIN3_VERSION_MAJOR=${PROJECT_VERSION_MINOR}) -ADD_DEFINITIONS(-DIN3_VERSION_MINOR=${PROJECT_VERSION_MINOR}) -ADD_DEFINITIONS(-DIN3_VERSION_PATCH=${PROJECT_VERSION_PATCH}) - - -# define output dir structure -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - +include(c/options.cmake) IF (WASM) - set(TEST false) - set(RECORDER false) - set(TRANSPORTS false) - set(BUILD_DOC false) - set(IN3_LIB false) - set(CMD false) - set(USE_CURL false) - set(USE_WINHTTP false) - set(THREADSAFE false) - ADD_DEFINITIONS(-DWASM) add_subdirectory(wasm/src) ENDIF (WASM) -if (THREADSAFE) - ADD_DEFINITIONS(-DTHREADSAFE) -ENDIF() - # build tests if(TEST) - ADD_DEFINITIONS(-DTEST) - ADD_DEFINITIONS(-DIN3_EXPORT_TEST=) - ADD_DEFINITIONS(-DIN3_IMPORT_TEST=extern) - ADD_DEFINITIONS(-DDEBUG) - SET(CMAKE_BUILD_TYPE Debug) - enable_testing() add_subdirectory(c/test) - add_custom_target(ptest COMMAND ${CMAKE_CTEST_COMMAND} -j 8) - add_custom_target(rtest COMMAND ${CMAKE_CTEST_COMMAND} -V ) -else(TEST) - ADD_DEFINITIONS(-DIN3_EXPORT_TEST=static) - ADD_DEFINITIONS(-DIN3_IMPORT_TEST=) endif(TEST) add_subdirectory(c) diff --git a/c/options.cmake b/c/options.cmake new file mode 100644 index 000000000..325b4a0b7 --- /dev/null +++ b/c/options.cmake @@ -0,0 +1,257 @@ + +# options +option(BUILD_DOC "generates the documenation with doxygen." OFF) +option(TAG_VERSION "the tagged version, which should be used" 3.0.0) +option(ETH_NANO "build minimal eth verification.(eth_getTransactionReceipt)" ON) +option(ETH_BASIC "build basic eth verification.(all rpc-calls except eth_call)" ON) +option(ETH_FULL "build full eth verification.(including eth_call)" ON) +option(IPFS "build IPFS verification" ON) +option(COLOR "Enable color codes for debug" ON) +option(BTC "if true, the bitcoin verifiers will be build" ON) +option(IN3API "build the USN-API which offer better interfaces and additional functions on top of the pure verification" ON) +option(USE_PRECOMPUTED_EC "if true the secp256k1 curve uses precompiled tables to boost performance. turning this off makes ecrecover slower, but saves about 37kb." ON) +option(LOGGING "if set logging and human readable error messages will be inculded in th executable, otherwise only the error code is used. (saves about 19kB)" ON) +option(EVM_GAS "if true the gas costs are verified when validating a eth_call. This is a optimization since most calls are only interessted in the result. EVM_GAS would be required if the contract uses gas-dependend op-codes." true) +option(IN3_LIB "if true a shared anmd static library with all in3-modules will be build." ON) +option(TEST "builds the tests and also adds special memory-management, which detects memory leaks, but will cause slower performance" OFF) +option(FAST_MATH "Math optimizations used in the EVM. This will also increase the filesize." OFF) +option(SEGGER_RTT "Use the segger real time transfer terminal as the logging mechanism" OFF) +option(CURL_BLOCKING "if true the curl-request will block until the response is received" OFF) +option(JAVA "build the java-binding (shared-lib and jar-file)" OFF) +option(JAVA_MULTI_LIBS "embedds multiple shared libs in the jar" OFF) +option(WASM "Includes the WASM-Build. In order to build it you need emscripten as toolchain. Usually you also want to turn off other builds in this case." OFF) +option(ASMJS "compiles the code as asm.js." OFF) +option(WASM_EMBED "embedds the wasm as base64-encoded into the js-file" ON) +option(WASM_EMMALLOC "use ther smaller EMSCRIPTEN Malloc, which reduces the size about 10k, but may be a bit slower" ON) +option(WASM_SYNC "intiaializes the WASM synchronisly, which allows to require and use it the same function, but this will not be supported by chrome (4k limit)" OFF) +option(CODE_COVERAGE "Builds targets with code coverage instrumentation. (Requires GCC or Clang)" OFF) +option(GCC_ANALYZER "GCC10 static code analyses" OFF) +option(PAY_ETH "support for direct Eth-Payment" OFF) +option(USE_SCRYPT "integrate scrypt into the build in order to allow decrypt_key for scrypt encoded keys." ON) +option(USE_CURL "if true the curl transport will be built (with a dependency to libcurl)" ON) +option(USE_WINHTTP "if true the winhttp transport will be built (with a dependency to winhttp)" OFF) +option(LEDGER_NANO "include support for nano ledger" OFF) +option(ESP_IDF "include support for ESP-IDF microcontroller framework" OFF) +option(ASSERTIONS "includes assertions into the code, which help track errors but may cost time during runtime" OFF) +OPTION(TRANSPORTS "builds transports, which may require extra libraries." ON) +OPTION(IN3_SERVER "support for proxy server as part of the cmd-tool, which allows to start the cmd-tool with the -p option and listens to the given port for rpc-requests" OFF) +OPTION(CMD "build the comandline utils" ON) +OPTION(RECORDER "enable recording option for reproduce executions" ON) +OPTION(POA "support POA verification including validatorlist updates" OFF) +OPTION(MULTISIG "add capapbility to sign with a multig. Currrently only gnosis safe is supported" ON) +OPTION(ZKSYNC "add RPC-function to handle zksync-payments" ON) +OPTION(ZKCRYPTO_LIB "Path to the static zkcrypto-lib" OFF) +OPTION(SENTRY "Enable Sentry" OFF) +OPTION(BTC_PRE_BPI34 "Enable BTC-Verfification for blocks before BIP34 was activated" ON) +OPTION(PK_SIGNER "Enable Signing with private keys" ON) +OPTION(NODESELECT_DEF "Enable default nodeselect implementation" ON) +OPTION(NODESELECT_DEF_WL "Enable default nodeselect whitelist implementation" ON) +OPTION(PLGN_CLIENT_DATA "Enable client-data plugin" OFF) +OPTION(THREADSAFE "uses mutex to protect shared nodelist access" ON) +OPTION(SWIFT "swift API for swift bindings" OFF) + + +IF (DEFINED ANDROID_ABI) + set(TRANSPORTS,false) + set(IN3_LIB,false) + set(USE_CURL,off) + set(CMD,false) + set(JAVA,true) + set(RECORDER,false) +ENDIF() +IF (SWIFT) + set(TRANSPORTS,false) + set(IN3_LIB,true) + set(USE_CURL, false) + set(CMD,false) + set(JAVA,false) + set(RECORDER,false) +ENDIF() + +IF (BTC_PRE_BPI34) + ADD_DEFINITIONS(-DBTC_PRE_BPI34) +ENDIF (BTC_PRE_BPI34) + +IF (POA) + ADD_DEFINITIONS(-DPOA) +ENDIF (POA) + +IF (PK_SIGNER) + ADD_DEFINITIONS(-DPK_SIGNER) + set(IN3_API ${IN3_API} pk_signer) +ENDIF (PK_SIGNER) + +if (USE_PRECOMPUTED_EC) + ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=1) +else() + ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=0) +endif() + +if (LOGGING) + ADD_DEFINITIONS(-DLOGGING) +endif() + +if (MULTISIG) + ADD_DEFINITIONS(-DMULTISIG) +endif() + +if (ZKSYNC) + ADD_DEFINITIONS(-DZKSYNC) + set(WASM_MODULES ${WASM_MODULES} zksync) + set(IN3_API ${IN3_API} zksync) +endif() + + +if(ETH_FULL) + ADD_DEFINITIONS(-DETH_FULL) + set(IN3_VERIFIER eth_full) + set(ETH_BASIC true) + set(ETH_NANO true) +elseif(ETH_BASIC) + ADD_DEFINITIONS(-DETH_BASIC) + set(IN3_VERIFIER eth_basic) + set(ETH_NANO true) +elseif(ETH_NANO) + ADD_DEFINITIONS(-DETH_NANO) + set(IN3_VERIFIER eth_nano) +endif() + +if (ETH_NANO) + set(WASM_MODULES ${WASM_MODULES} eth) +endif() + +if(IN3API) + ADD_DEFINITIONS(-DETH_API) + set(IN3_API ${IN3_API} eth_api) +endif() + +if (ESP_IDF) + ADD_DEFINITIONS(-DESP_IDF) +endif() + +if(PAY_ETH) + ADD_DEFINITIONS(-DPAY_ETH -DPAY) + set(IN3_API ${IN3_API} pay_eth) +endif() + +if(IPFS) + ADD_DEFINITIONS(-DIPFS) + set(IN3_VERIFIER ${IN3_VERIFIER} ipfs) + set(WASM_MODULES ${WASM_MODULES} ipfs) + + if(IN3API) + set(IN3_API ${IN3_API} ipfs_api) + endif() +endif() + +if(BTC) + ADD_DEFINITIONS(-DBTC) + set(IN3_VERIFIER ${IN3_VERIFIER} btc) + set(WASM_MODULES ${WASM_MODULES} btc) + if(IN3API) + set(IN3_API ${IN3_API} btc_api) + endif() +endif() + +if(LEDGER_NANO) + add_definitions(-DLEDGER_NANO) +endif() + +if(COLOR AND NOT (MSVC OR MSYS OR MINGW)) + ADD_DEFINITIONS(-DLOG_USE_COLOR) +endif() + + +if(CMAKE_BUILD_TYPE MATCHES Debug) + ADD_DEFINITIONS(-DDEBUG) +endif(CMAKE_BUILD_TYPE MATCHES Debug) + +if(EVM_GAS) + ADD_DEFINITIONS(-DEVM_GAS) +endif(EVM_GAS) + +if(FAST_MATH) + ADD_DEFINITIONS(-DIN3_MATH_FAST) +else() + ADD_DEFINITIONS(-DIN3_MATH_LITE) +endif(FAST_MATH) + +if(SEGGER_RTT) + ADD_DEFINITIONS(-DSEGGER_RTT) +endif(SEGGER_RTT) + +if(RECORDER) + ADD_DEFINITIONS(-DRECORDER) +endif(RECORDER) + +if (SENTRY) + ADD_DEFINITIONS(-DSENTRY) + set(IN3_API ${IN3_API} in3_sentry) +endif() + +if (NODESELECT_DEF) + ADD_DEFINITIONS(-DNODESELECT_DEF) + if (NODESELECT_DEF_WL) + ADD_DEFINITIONS(-DNODESELECT_DEF_WL) + endif() + set(IN3_NODESELECT ${IN3_NODESELECT} nodeselect_def) +endif() + +# handle version +if (TAG_VERSION) + set(PROJECT_VERSION "${TAG_VERSION}") +else(TAG_VERSION) + set(PROJECT_VERSION "3.0.0-local") +endif(TAG_VERSION) + +MESSAGE(STATUS "Building version ${PROJECT_VERSION}") + +string(REPLACE "." ";" VERSION_LIST ${PROJECT_VERSION}) +list(GET VERSION_LIST 0 PROJECT_VERSION_MAJOR) +list(GET VERSION_LIST 1 PROJECT_VERSION_MINOR) +list(GET VERSION_LIST 2 PROJECT_VERSION_PATCH) + +ADD_DEFINITIONS("-DIN3_VERSION=\"${PROJECT_VERSION}\"") +ADD_DEFINITIONS(-DIN3_VERSION_MAJOR=${PROJECT_VERSION_MINOR}) +ADD_DEFINITIONS(-DIN3_VERSION_MINOR=${PROJECT_VERSION_MINOR}) +ADD_DEFINITIONS(-DIN3_VERSION_PATCH=${PROJECT_VERSION_PATCH}) + + +# define output dir structure +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + + +IF (WASM) + set(TEST false) + set(RECORDER false) + set(TRANSPORTS false) + set(BUILD_DOC false) + set(IN3_LIB false) + set(CMD false) + set(USE_CURL false) + set(USE_WINHTTP false) + set(THREADSAFE false) + ADD_DEFINITIONS(-DWASM) +ENDIF (WASM) + +if (THREADSAFE) + ADD_DEFINITIONS(-DTHREADSAFE) +ENDIF() + + +# build tests +if(TEST) + ADD_DEFINITIONS(-DTEST) + ADD_DEFINITIONS(-DIN3_EXPORT_TEST=) + ADD_DEFINITIONS(-DIN3_IMPORT_TEST=extern) + ADD_DEFINITIONS(-DDEBUG) + SET(CMAKE_BUILD_TYPE Debug) + enable_testing() + add_custom_target(ptest COMMAND ${CMAKE_CTEST_COMMAND} -j 8) + add_custom_target(rtest COMMAND ${CMAKE_CTEST_COMMAND} -V ) +else(TEST) + ADD_DEFINITIONS(-DIN3_EXPORT_TEST=static) + ADD_DEFINITIONS(-DIN3_IMPORT_TEST=) +endif(TEST) From ec0d9f729bdd7a4bfbdfb79229161a2a7ad35538 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 15 Apr 2021 20:06:10 +0200 Subject: [PATCH 131/221] fix path issue in tests --- c/test/CMakeLists.txt | 6 ++++++ c/test/test_utils.h | 14 ++++++++------ c/test/unit_tests/test_abi.c | 2 +- c/test/util/transport.c | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/c/test/CMakeLists.txt b/c/test/CMakeLists.txt index f95461b9a..d279ae023 100644 --- a/c/test/CMakeLists.txt +++ b/c/test/CMakeLists.txt @@ -41,6 +41,12 @@ else() endif() include_directories(. ../src) +get_filename_component(testdata_dir "${CMAKE_CURRENT_LIST_DIR}/testdata" ABSOLUTE) + +#file(RELATIVE_PATH testdata_dir "${CMAKE_BINARY_DIR}" "testdata") +add_definitions("-DTESTDATA_DIR=\"${testdata_dir}\"") +get_filename_component(buildDirRelFilePath "${myFile}" + REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") # handle codecoverage if (CODE_COVERAGE) diff --git a/c/test/test_utils.h b/c/test/test_utils.h index cb7869ee6..40c013a47 100644 --- a/c/test/test_utils.h +++ b/c/test/test_utils.h @@ -47,16 +47,18 @@ #ifdef __cplusplus extern "C" { #endif - -#define TESTS_BEGIN() UNITY_BEGIN() -#define TESTS_END() UNITY_END() -#define TEST_LOG(fmt_, ...) printf("%s:%d:%s:LOG:" fmt_, __FILE__, __LINE__, __func__, __VA_ARGS__) +#ifndef TESTDATA_DIR +#define TESTDATA_DIR "../c/test/testdata" +#endif +#define TESTS_BEGIN() UNITY_BEGIN() +#define TESTS_END() UNITY_END() +#define TEST_LOG(fmt_, ...) printf("%s:%d:%s:LOG:" fmt_, __FILE__, __LINE__, __func__, __VA_ARGS__) #define TEST_LOG_INTERNAL(f_, fmt_, ...) printf("%s:%d:%s:LOG:" fmt_, __FILE__, __LINE__, f_, __VA_ARGS__) // Timing #define TIMING_START() gettimeofday(&begin, NULL) -#define TIMING_END() gettimeofday(&end, NULL) -#define TIMING_GET() ((double) (end.tv_usec - begin.tv_usec) / 1000000 + (double) (end.tv_sec - begin.tv_sec)) +#define TIMING_END() gettimeofday(&end, NULL) +#define TIMING_GET() ((double) (end.tv_usec - begin.tv_usec) / 1000000 + (double) (end.tv_sec - begin.tv_sec)) #define RUN_TIMED_TEST(t) \ do { \ diff --git a/c/test/unit_tests/test_abi.c b/c/test/unit_tests/test_abi.c index afccc38b6..928f67bde 100644 --- a/c/test/unit_tests/test_abi.c +++ b/c/test/unit_tests/test_abi.c @@ -211,7 +211,7 @@ static void test_abi_tuples() { "0000000000000000000000000000000000000000000000001234567890abcdef0000000000000000000000000000000000000000000000000000000000000000") } static void test_json() { - char* json_data = read_json_response_buffer("../c/test/testdata/api/abi.json"); + char* json_data = read_json_response_buffer(TESTDATA_DIR "/api/abi.json"); TEST_ASSERT_NOT_NULL_MESSAGE(json_data, "You must start this test from build-directory"); json_ctx_t* jctx = parse_json(json_data); TEST_ASSERT_NOT_NULL_MESSAGE(jctx, "Invalid json"); diff --git a/c/test/util/transport.c b/c/test/util/transport.c index c491d6fa4..9955cc55c 100644 --- a/c/test/util/transport.c +++ b/c/test/util/transport.c @@ -6,7 +6,7 @@ #include "nodeselect/full/nodelist.h" #include #include -#define MOCK_PATH "../c/test/testdata/mock/%s.json" +#define MOCK_PATH TESTDATA_DIR "/mock/%s.json" static void clean_json_str(char* s) { const char* d = s; From 9625847357561dd88bc13cbf5d5bb42da773d50a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 15 Apr 2021 22:58:29 +0200 Subject: [PATCH 132/221] fix rust --- CMakeLists.txt | 2 +- rust/ci.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b14c2f810..0362c7516 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/scripts/cmake_mo # project name project(in3) -include(c/options.cmake) +include("c/options.cmake") IF (WASM) add_subdirectory(wasm/src) diff --git a/rust/ci.yml b/rust/ci.yml index 5b4c95e85..e11ca4919 100644 --- a/rust/ci.yml +++ b/rust/ci.yml @@ -34,7 +34,7 @@ - export RUST_TEST_THREADS=1 - export OPENSSL_DIR=/usr/lib/ssl - mkdir -p rust/in3-sys/in3-core/c - - cp -r c/CMakeLists.txt c/macro.cmake c/compiler.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ + - cp -r c/CMakeLists.txt c/*.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ - cp CMakeLists.txt rust/in3-sys/in3-core/ - cd rust/ - export UPDATE_IN3_BINDINGS=1 @@ -83,7 +83,7 @@ rust_valgrind: script: - export RUST_BACKTRACE=1 - mkdir -p rust/in3-sys/in3-core/c - - cp -r c/CMakeLists.txt c/macro.cmake c/compiler.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ + - cp -r c/CMakeLists.txt c/*.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ - cp CMakeLists.txt rust/in3-sys/in3-core/ - export UPDATE_IN3_BINDINGS=1 - cd rust @@ -105,7 +105,7 @@ rust: script: - export RUST_BACKTRACE=1 - mkdir -p rust/in3-sys/in3-core/c - - cp -r c/CMakeLists.txt c/macro.cmake c/compiler.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ + - cp -r c/CMakeLists.txt c/*.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ - cp CMakeLists.txt rust/in3-sys/in3-core/ - cd rust/ - export UPDATE_IN3_BINDINGS=1 @@ -129,7 +129,7 @@ deploy_rust: - cargo login $CARGO_TOKEN script: - mkdir -p rust/in3-sys/in3-core/c - - cp -r c/CMakeLists.txt c/macro.cmake c/compiler.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ + - cp -r c/CMakeLists.txt c/*.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ - cp CMakeLists.txt rust/in3-sys/in3-core/ - find rust -name 'Cargo.toml' -exec sed -i '' -e "s/version = \"0.0.0\"/version = \""${CI_COMMIT_TAG:1}"\"/g" {} \; - cd rust/ From d4f600d87a2ca5cea5114d002695067abd7cfca4 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 15 Apr 2021 23:00:11 +0200 Subject: [PATCH 133/221] fix rust --- scripts/build_rust.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_rust.sh b/scripts/build_rust.sh index cfabd35f1..6d986f376 100755 --- a/scripts/build_rust.sh +++ b/scripts/build_rust.sh @@ -2,7 +2,7 @@ cd .. mkdir -p rust/in3-sys/in3-core mkdir -p rust/in3-sys/in3-core/c -cp -r c/CMakeLists.txt c/macro.cmake c/compiler.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ +cp -r c/CMakeLists.txt c/*.cmake c/docs c/src c/include rust/in3-sys/in3-core/c/ cp CMakeLists.txt rust/in3-sys/in3-core/ export UPDATE_IN3_BINDINGS=1 cd rust && cargo clean && cargo build From b709ae31686eb7ea500dfa5aa743163e8b3616cb Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 16 Apr 2021 13:04:39 +0200 Subject: [PATCH 134/221] refactored generator --- c/src/cmd/in3/helper.c | 4 + scripts/build_rpc.sh | 3 + scripts/generator/generate.js | 262 ++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100755 scripts/build_rpc.sh create mode 100755 scripts/generator/generate.js diff --git a/c/src/cmd/in3/helper.c b/c/src/cmd/in3/helper.c index e983598b1..9dcde913f 100644 --- a/c/src/cmd/in3/helper.c +++ b/c/src/cmd/in3/helper.c @@ -40,7 +40,11 @@ #include "../../api/eth1/eth_api.h" #include "../../signer/pk-signer/signer.h" #include "../../tools/recorder/recorder.h" +#ifdef CMD_ARGS_FILE +#include CMD_ARGS_FILE +#else #include "args.h" +#endif #include "handlers.h" #include "transport.h" #include "tx.h" diff --git a/scripts/build_rpc.sh b/scripts/build_rpc.sh new file mode 100755 index 000000000..e9cc26c47 --- /dev/null +++ b/scripts/build_rpc.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +generator/generate.js --src=../c/src --doc=../../../doc/docs --zsh=_in3.template --arg=../c/src/cmd/in3/args.h \ No newline at end of file diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js new file mode 100755 index 000000000..76234b37a --- /dev/null +++ b/scripts/generator/generate.js @@ -0,0 +1,262 @@ +#!/usr/bin/env node + +const yaml = require('yaml') +const fs = require('fs') +const { + getType, + asArray, + camelCaseLow, + camelCaseUp, + link, + toCmdParam, + short_descr +} = require('./util') + +const pargs = process.argv.slice(2) +const in3_core_dir = process.argv[1].replace('/scripts/generator/generate.js', '') +const src_dirs = [] +const doc_dir = [] +const args_file = [] +const zsh_file = [] +const generators = [] +process.argv.slice(2).forEach(a => { + if (a.startsWith('--src=')) src_dirs.push(a.substr(6)) + else if (a.startsWith('--doc=')) doc_dir.push(a.substr(6)) + else if (a.startsWith('--arg=')) args_file.push(a.substr(6)) + else if (a.startsWith('--zsh=')) zsh_file.push(a.substr(6)) + else if (a.startsWith('--gen=')) generators.push(a.substr(6)) + else throw new Error('Invalid argument : ' + a) +}) +if (!src_dirs.length) src_dirs.push('../c/src') + +//const doc_dir = process.argv[process.argv.length - 1] +const main_conf = yaml.parse(fs.readFileSync(in3_core_dir + '/c/src/cmd/in3/in3.yml', 'utf-8')) +const typeName = (def, code) => (code ? '`' : '') + ((def.key ? '{key:$t}' : (def.array ? '$t[]' : "$t")) + (def.optional ? '?' : '')).replace('$t', typeof (def.type) === 'string' ? def.type : 'object') + (code ? '`' : '') +const rpc_doc = [] +const config_doc = [] +const main_help = [] +const main_aliases = [] +const bool_props = [] + +let docs = {}, config = {}, types = {} + + +function scan(dir) { + for (const f of fs.readdirSync(dir, { withFileTypes: true })) { + if (f.name == 'rpc.yml') { + console.error('parse ' + dir + '/' + f.name) + const ob = yaml.parse(fs.readFileSync(dir + '/' + f.name, 'utf-8')) + if (ob.types) { + types = { ...types, ...ob.types } + delete ob.types + } + for (const k of Object.keys(ob)) { + if (ob[k].config) config = { ...config, ...ob[k].config } + delete ob[k].config + docs[k] = { ...docs[k], ...ob[k] } + } + } + else if (f.isDirectory()) scan(dir + '/' + f.name) + } +} + + + +function print_object(def, pad, useNum, doc) { + let i = 1 + for (const prop of Object.keys(def)) { + let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' + const p = def[prop] + const pt = getType(p.type, types) + if (p.type) s += ' : ' + typeName(p, true) + if (p.optional) s += ' *(optional)*' + if (p.descr) s += ' - ' + p.descr + if (p.key) s += ' with ' + p.key + ' as keys in the object' + if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' + if (p.enum) s += '\n' + pad + 'Possible Values are:\n\n' + Object.keys(p.enum).map(v => pad + ' - `' + v + '` : ' + p.enum[v]).join('\n') + '\n' + if (p.alias) s += '\n' + pad + 'The data structure of ' + prop + ' is the same as ' + link(p.alias) + '. See Details there.' + doc.push(s) + if (typeof pt === 'object') { + rpc_doc.push('The ' + prop + ' object supports the following properties :\n' + pad) + print_object(pt, pad + ' ', false, doc) + } + if (p.example) rpc_doc.push('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) + doc.push(pad + '\n') + } +} + + +function handle_config(conf, pre, title, descr) { + if (title) config_doc.push('\n## ' + title + '\n') + for (const key of Object.keys(conf)) { + const c = conf[key] + // handle bindings + generators.forEach(_ => _.updateConfig(pre, c, key)) + + // handle doc + if (!pre) { + let s = '\n' + (title ? '#' : '') + '## ' + key + '\n\n' + c.descr + if (c.optional) s += ' *This config is optional.*' + if (c.default) s += ' (default: `' + JSON.stringify(c.default) + '`)' + if (c.type) s += '\n\n Type: ' + typeName(c, true) + if (c.enum) s += '\n\nPossible Values are:\n\n' + Object.keys(c.enum).map(v => '- `' + v + '` : ' + c.enum[v]).join('\n') + '\n' + config_doc.push(s) + if (typeof (c.type) === 'object') { + config_doc.push('The ' + key + ' object supports the following properties :\n') + print_object(c.type, '', false, config_doc) + } + if (c.example !== undefined) { + config_doc.push('\n*Example:*\n') + asArray(c.example).forEach(ex => { + config_doc.push('```sh') + if (typeof (ex) == 'object') + config_doc.push('> in3 ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') + else + config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') + config_doc.push('```\n') + if (!title) + config_doc.push('```js\nconst in3 = new IN3(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') + }) + + } + } + asArray(c.cmd).forEach(_ => main_aliases.push(' "' + _ + '", "' + (c.alias || (pre + key + (c.type == 'bool' ? '=true' : ''))) + '",')); + if (c.type == 'bool') bool_props.push(pre + key); + main_help.push(('--' + pre + key).padEnd(30) + (c.cmd ? ('-' + c.cmd) : '').padEnd(7) + short_descr(c.descr)) + let s = '' + if (c.descr) s += '[' + short_descr(c.descr) + ']' + if (c.type != 'bool') + s += ':' + key + ':(' + (c.enum ? Object.keys(c.enum).join(' ') : '') + ')' + if (typeof (c.type) === 'object') + handle_config(c.type, pre + key + '.') + else { + zsh_conf.push("'--" + pre + key + (c.type != 'bool' ? '=' : '') + s + "'") + asArray(c.cmd).forEach(_ => zsh_conf.push("'-" + _ + s + "'")) + } + } +} + +src_dirs.forEach(scan) +docs.config.in3_config.params.config.type = config +rpc_doc.push('# API RPC\n\n') +rpc_doc.push('This section describes the behavior for each RPC-method supported with incubed.\n\nThe core of incubed is to execute rpc-requests which will be send to the incubed nodes and verified. This means the available RPC-Requests are defined by the clients itself.\n\n') +config_doc.push('# Configuration\n\n') +config_doc.push('When creating a new Incubed Instance you can configure it. The Configuration depends on the registered plugins. This page describes the available configuration parameters.\n\n') +let zsh_cmds = [], zsh_conf = [] +for (const s of Object.keys(docs).sort()) { + const rpcs = docs[s] + const rdescr = rpcs.descr + + rpc_doc.push("## " + s + "\n\n") + if (rdescr) rpc_doc.push(rdescr + '\n') + delete rpcs.descr + + for (const rpc of Object.keys(rpcs).sort()) { + const def = rpcs[rpc] + def.returns = def.returns || def.result + def.result = def.returns || def.result + let z = " '" + rpc + ': ' + short_descr((def.descr || (def.alias && rpcs[def.alias].descr) || '')) + + rpc_doc.push('### ' + rpc + '\n\n') + asArray(def.alias).forEach(_ => rpc_doc.push(rpc + ' is just an alias for ' + link(_) + '.See Details there.\n\n')) + if (def.descr) + rpc_doc.push(def.descr + '\n') + if (def.params) { + rpc_doc.push("*Parameters:*\n") + print_object(def.params, '', true, rpc_doc) + rpc_doc.push() + z += ' ' + Object.keys(def.params).map(_ => '<' + _ + '>').join(' ') + } + else if (!def.alias) + rpc_doc.push("*Parameters:* - \n") + if (def.in3Params) { + rpc_doc.push('The following in3-configuration will have an impact on the result:\n\n'); + print_object(getType(def.in3Params, types), '', false, rpc_doc) + rpc_doc.push() + } + if (def.validation) rpc_doc.push('\n' + def.validation + '\n') + + if (def.returns) { + if (def.returns.type) { + rpc_doc.push('*Returns:* ' + typeName(def.returns, true) + '\n\n' + def.returns.descr + '\n') + const pt = getType(def.returns.type, types) + if (typeof pt === 'object') { + rpc_doc.push('\nThe return value contains the following properties :\n') + print_object(pt, '', false, rpc_doc) + } + } + else if (def.returns.alias) + rpc_doc.push('*Returns:*\n\nThe Result of `' + rpc + '` is the same as ' + link(def.returns.alias) + '. See Details there.\n') + else + rpc_doc.push('*Returns:*\n\n' + (def.returns.descr || '') + '\n') + } + + if (def.proof) { + rpc_doc.push('*Proof:*\n\n' + (def.proof.descr || '') + '\n') + const pt = getType(def.proof.type, types) + if (def.proof.alias) + rpc_doc.push('The proof will be calculated as described in ' + link(def.proof.alias) + '. See Details there.\n\n') + + if (pt) { + rpc_doc.push("This proof section contains the following properties:\n\n") + print_object(pt, '', false, rpc_doc) + rpc_doc.push("\n\n") + } + } + + asArray(def.example).forEach(ex => { + const req = { method: rpc, params: ex.request || [] } + if (def.proof) req.in3 = { "verification": "proof", ...ex.in3Params } + const data = { result: ex.response || null } + const is_json = (typeof data.result == 'object' || Array.isArray(data.result)) + if (ex.in3) data.in3 = ex.in3 + + rpc_doc.push('*Example:*\n') + if (ex.descr) rpc_doc.push('\n' + ex.descr + '\n') + + /* + rpc_doc.push('```yaml\n# ---- Request -----\n\n' + yaml.stringify(req)) + rpc_doc.push('\n# ---- Response -----\n\n' + yaml.stringify(data)) + rpc_doc.push('```\n') + */ + rpc_doc.push('```sh\n> in3 ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) + rpc_doc.push(is_json ? JSON.stringify(data.result, null, 2) : '' + data.result) + rpc_doc.push('```\n') + + rpc_doc.push('```js\n//---- Request -----\n\n' + JSON.stringify(req, null, 2)) + rpc_doc.push('\n//---- Response -----\n\n' + JSON.stringify(data, null, 2)) + rpc_doc.push('```\n') + + }) + z += "'" + zsh_cmds.push(z) + } + console.log('generate ' + s + '\n ' + Object.keys(rpcs).join('\n ')) + + if (Object.values(rpcs).filter(_ => !_.skipApi).length) + generators.forEach(_ => _.generateAPI(s, rpcs, rdescr, types)) + +} + +handle_config(config, '') + +generators.forEach(_ => _.generate_config()) + +handle_config(main_conf.config, '', 'cmdline options\n\nThose special options are used in the comandline client to pass additional options.\n') +main_help.push('') +main_help.push('In addition to the documented rpc-methods, those methods are also supported:') +main_help.push('') +Object.keys(main_conf.rpc).forEach(k => { + (k + ' ' + main_conf.rpc[k]).split("\n").map(_ => _.trim()).map((_, i) => i ? ' ' + _ : _) + .forEach(l => main_help.push(l)) +}) + +if (zsh_file.length) + fs.writeFileSync(zsh_file[0].replace('.template', '.sh'), fs.readFileSync(zsh_file[0], 'utf8').replace('$CMDS', zsh_cmds.join('\n')).replace('$CONFS', zsh_conf.join('\n')), { encoding: 'utf8' }) +if (doc_dir.length) { + fs.writeFileSync(doc_dir[0] + '/rpc.md', rpc_doc.join('\n') + '\n', { encoding: 'utf8' }) + fs.writeFileSync(doc_dir[0] + '/config.md', config_doc.join('\n') + '\n', { encoding: 'utf8' }) +} +if (args_file.length) + fs.writeFileSync(args_file[0], '// This is a generated file, please don\'t edit it manually!\n\n#include \n\nconst char* bool_props[] = {' + bool_props.map(_ => '"' + _ + '", ').join('') + 'NULL};\n\nconst char* help_args = "\\\n' + main_help.map(_ => _ + '\\n').join('\\\n') + '";\n\nconst char* aliases[] = {\n' + main_aliases.join('\n') + '\n NULL};\n', { encoding: 'utf8' }) + From 9d10608d04c29a2e78771b1b97bd5976043f0c8a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 16 Apr 2021 13:05:14 +0200 Subject: [PATCH 135/221] fixed require --- scripts/generator/generate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js index 76234b37a..a4eb1ef9b 100755 --- a/scripts/generator/generate.js +++ b/scripts/generator/generate.js @@ -24,7 +24,7 @@ process.argv.slice(2).forEach(a => { else if (a.startsWith('--doc=')) doc_dir.push(a.substr(6)) else if (a.startsWith('--arg=')) args_file.push(a.substr(6)) else if (a.startsWith('--zsh=')) zsh_file.push(a.substr(6)) - else if (a.startsWith('--gen=')) generators.push(a.substr(6)) + else if (a.startsWith('--gen=')) generators.push(require(a.substr(6))) else throw new Error('Invalid argument : ' + a) }) if (!src_dirs.length) src_dirs.push('../c/src') From ee2cece29a92b0442218ce9c816f85273aa01d34 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 16 Apr 2021 17:28:00 +0200 Subject: [PATCH 136/221] fixed rust --- c/src/tools/swift/swift.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/c/src/tools/swift/swift.h b/c/src/tools/swift/swift.h index 47c8f0030..92a525b11 100644 --- a/c/src/tools/swift/swift.h +++ b/c/src/tools/swift/swift.h @@ -33,15 +33,19 @@ *******************************************************************************/ #ifndef IN3_SWIFT_H #define IN3_SWIFT_H - +#ifdef __clang__ +#define _NONULL _Nonnull +#else +#define _NONULL +#endif #include "../../core/client/plugin.h" typedef struct in3_swift_cb { - in3_ret_t (*_Nonnull cache_get)(in3_cache_ctx_t* _Nonnull ctx); - in3_ret_t (*_Nonnull cache_set)(in3_cache_ctx_t* _Nonnull ctx); - in3_ret_t (*_Nonnull cache_clear)(); + in3_ret_t (*_NONULL cache_get)(in3_cache_ctx_t* _Nonnull ctx); + in3_ret_t (*_NONULL cache_set)(in3_cache_ctx_t* _Nonnull ctx); + in3_ret_t (*_NONULL cache_clear)(); } swift_cb_t; -in3_ret_t in3_register_swift(in3_t* _Nonnull c, swift_cb_t* _Nonnull cbs); +in3_ret_t in3_register_swift(in3_t* _NONULL c, swift_cb_t* _NONULL cbs); #endif //IN3_SWIFT_H From e0c0c2708fce892b948dfa8d26d79338d73ac703 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 16 Apr 2021 17:34:29 +0200 Subject: [PATCH 137/221] fix swift --- c/include/in3.rs.h | 2 ++ c/options.cmake | 1 + scripts/build_includeh.sh | 2 ++ 3 files changed, 5 insertions(+) diff --git a/c/include/in3.rs.h b/c/include/in3.rs.h index 2dabd57d0..bbfe9d081 100644 --- a/c/include/in3.rs.h +++ b/c/include/in3.rs.h @@ -13,5 +13,7 @@ #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" +#ifdef SWIFT #include "../src/tools/swift/swift.h" +#endif #include "../src/third-party/tommath/tommath.h" diff --git a/c/options.cmake b/c/options.cmake index 325b4a0b7..ddd2f4adf 100644 --- a/c/options.cmake +++ b/c/options.cmake @@ -60,6 +60,7 @@ IF (DEFINED ANDROID_ABI) set(RECORDER,false) ENDIF() IF (SWIFT) + ADD_DEFINITIONS(-DSWIFT) set(TRANSPORTS,false) set(IN3_LIB,true) set(USE_CURL, false) diff --git a/scripts/build_includeh.sh b/scripts/build_includeh.sh index 751a8fb59..54bb30bba 100755 --- a/scripts/build_includeh.sh +++ b/scripts/build_includeh.sh @@ -47,6 +47,8 @@ cat <../c/include/in3.rs.h #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" +#ifdef SWIFT #include "../src/tools/swift/swift.h" +#endif #include "../src/third-party/tommath/tommath.h" EOF From d5799d965a90c152a7f63ab50d4fae81e4193145 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 16 Apr 2021 17:45:57 +0200 Subject: [PATCH 138/221] generate swift-headers --- c/include/in3.rs.h | 4 ---- c/include/in3.swift.h | 17 +++++++++++++++ scripts/build_includeh.sh | 21 ++++++++++++++++-- scripts/create_swift_junit.js | 40 ----------------------------------- 4 files changed, 36 insertions(+), 46 deletions(-) create mode 100644 c/include/in3.swift.h delete mode 100755 scripts/create_swift_junit.js diff --git a/c/include/in3.rs.h b/c/include/in3.rs.h index bbfe9d081..f03fa7636 100644 --- a/c/include/in3.rs.h +++ b/c/include/in3.rs.h @@ -13,7 +13,3 @@ #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" -#ifdef SWIFT -#include "../src/tools/swift/swift.h" -#endif -#include "../src/third-party/tommath/tommath.h" diff --git a/c/include/in3.swift.h b/c/include/in3.swift.h new file mode 100644 index 000000000..2dabd57d0 --- /dev/null +++ b/c/include/in3.swift.h @@ -0,0 +1,17 @@ +// AUTO-GENERATED FILE +// See scripts/build_includeh.sh +#include "../src/core/client/request_internal.h" +#include "../src/signer/pk-signer/signer.h" +#include "../src/tools/clientdata/client_data.h" +#include "../src/api/btc/btc_api.h" +#include "in3/bytes.h" +#include "in3/client.h" +#include "in3/request.h" +#include "in3/plugin.h" +#include "in3/error.h" +#include "in3/eth_api.h" +#include "in3/in3_curl.h" +#include "in3/in3_init.h" +#include "in3/log.h" +#include "../src/tools/swift/swift.h" +#include "../src/third-party/tommath/tommath.h" diff --git a/scripts/build_includeh.sh b/scripts/build_includeh.sh index 54bb30bba..31d226e05 100755 --- a/scripts/build_includeh.sh +++ b/scripts/build_includeh.sh @@ -47,8 +47,25 @@ cat <../c/include/in3.rs.h #include "in3/in3_curl.h" #include "in3/in3_init.h" #include "in3/log.h" -#ifdef SWIFT +EOF + +# create swift binding header +cat <../c/include/in3.swift.h +// AUTO-GENERATED FILE +// See scripts/build_includeh.sh +#include "../src/core/client/request_internal.h" +#include "../src/signer/pk-signer/signer.h" +#include "../src/tools/clientdata/client_data.h" +#include "../src/api/btc/btc_api.h" +#include "in3/bytes.h" +#include "in3/client.h" +#include "in3/request.h" +#include "in3/plugin.h" +#include "in3/error.h" +#include "in3/eth_api.h" +#include "in3/in3_curl.h" +#include "in3/in3_init.h" +#include "in3/log.h" #include "../src/tools/swift/swift.h" -#endif #include "../src/third-party/tommath/tommath.h" EOF diff --git a/scripts/create_swift_junit.js b/scripts/create_swift_junit.js deleted file mode 100755 index 059ae2758..000000000 --- a/scripts/create_swift_junit.js +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env node - -const readline = require('readline'); -var rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: false -}); -let content = '' -let suite = '' -console.log("\n\n") -rl.on('line', line => { - if (line.startsWith('Test Suite')) return - - if (line.startsWith('Test Case')) { - if (line.indexOf('started') > 0) { - const m = (/\[([a-zA-Z0-9\.]+)\s+(\w+)/gm).exec(line) - content = '' - if (m[1] != suite) { - if (suite) console.log(' ') - console.log(' ') - } - console.log(' ') - } - else { - if (line.indexOf(' failed ') > 0) - console.log(' ') - console.log(' ') - } - } - else - content += line + '\n' -}) -rl.on('close', () => { - console.log(" \n") -}) \ No newline at end of file From 032967b59841cfca3b2e88be4727de10f90dcfeb Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 19 Apr 2021 23:58:45 +0200 Subject: [PATCH 139/221] fixed rpc --- c/src/verifier/eth1/basic/rpc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 9db37e6e4..9086a42b3 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -188,7 +188,7 @@ eth: result: type: blockdataWithTxHashes - params: - fullTx: false + fullTx: true name: getBlockWithTx descr: returns the given Block by number with full transaction data. if no blocknumber is specified the latest block will be returned. result: From d30be137deefdbc483c5741785776f96ea5fbd62 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 20 Apr 2021 09:14:19 +0200 Subject: [PATCH 140/221] made registry args optional --- c/src/nodeselect/full/rpc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/src/nodeselect/full/rpc.yml b/c/src/nodeselect/full/rpc.yml index 2e88044f5..2c137d18a 100644 --- a/c/src/nodeselect/full/rpc.yml +++ b/c/src/nodeselect/full/rpc.yml @@ -73,6 +73,7 @@ nodelist: type: contract: descr: address of the registry contract. (This is the data-contract!) + optional: true type: address whiteListContract: @@ -89,6 +90,7 @@ nodelist: registryId: descr: identifier of the registry. type: bytes32 + optional: true needsUpdate: descr: if set, the nodeList will be updated before next request. From 516d2103622a69da86509bfcfa4929fe285c90d7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 21 Apr 2021 13:23:08 +0200 Subject: [PATCH 141/221] rename cmd-util --- c/src/cmd/in3/CMakeLists.txt | 15 +++++++++++---- c/src/cmd/in3/helper.c | 5 +++-- c/src/cmd/in3/in3.yml | 2 +- c/src/cmd/in3/option_handler.c | 8 ++++++-- scripts/generator/generate.js | 10 +++++++--- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/c/src/cmd/in3/CMakeLists.txt b/c/src/cmd/in3/CMakeLists.txt index 41eec10fb..4edf499de 100644 --- a/c/src/cmd/in3/CMakeLists.txt +++ b/c/src/cmd/in3/CMakeLists.txt @@ -32,6 +32,12 @@ # with this program. If not, see . ############################################################################### +if ( NOT CMD_NAME ) + set(CMD_NAME in3) +endif () + +ADD_DEFINITIONS("-DCMD_NAME=\"${CMD_NAME}\"") + IF (IN3_SERVER) ADD_DEFINITIONS(-DIN3_SERVER) set(LIBS ${LIBS} http_server) @@ -45,7 +51,8 @@ if (MULTISIG) set(LIBS ${LIBS} multisig) endif() -add_executable(in3 + +add_executable(${CMD_NAME} helper.c main.c option_handler.c @@ -57,11 +64,11 @@ add_executable(in3 in3_storage.c ../../tools/recorder/recorder.c ) -target_compile_definitions(in3 PRIVATE _XOPEN_SOURCE=600) +target_compile_definitions(${CMD_NAME} PRIVATE _XOPEN_SOURCE=600) -target_link_libraries(in3 init pk_signer ${LIBS} -lm) +target_link_libraries(${CMD_NAME} init pk_signer ${LIBS} -lm) -install(TARGETS in3 +install(TARGETS ${CMD_NAME} DESTINATION /usr/local/bin/ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE diff --git a/c/src/cmd/in3/helper.c b/c/src/cmd/in3/helper.c index 9dcde913f..c37fa4da2 100644 --- a/c/src/cmd/in3/helper.c +++ b/c/src/cmd/in3/helper.c @@ -92,11 +92,12 @@ static bool is_number(char* val) { void configure_opt(in3_t* c, char* name, char* value, int argc, char** argv) { sb_t sb = {0}; - // handle options if (handle_option(c, name, value, &sb, argc, argv)) return; if (!sb.data) { - char* p = strtok(name, "."); + char* _name = alloca(strlen(name + 1)); + strcpy(_name, name); + char* p = strtok(_name, "."); sb_add_char(&sb, '{'); int b = 1; while (p) { diff --git a/c/src/cmd/in3/in3.yml b/c/src/cmd/in3/in3.yml index e8c0d8afb..f964e569c 100644 --- a/c/src/cmd/in3/in3.yml +++ b/c/src/cmd/in3/in3.yml @@ -167,7 +167,7 @@ config: onlysign: cmd: os type: bool - descr: only sign, don't send the raw Transaction + descr: only sign, do not send the raw Transaction example: true noproof: alias: proof=none diff --git a/c/src/cmd/in3/option_handler.c b/c/src/cmd/in3/option_handler.c index 4b267248f..ab09e2234 100644 --- a/c/src/cmd/in3/option_handler.c +++ b/c/src/cmd/in3/option_handler.c @@ -11,6 +11,10 @@ #include "tx.h" #include "weights.h" +#ifndef CMD_NAME +#define CMD_NAME "in3" +#endif + #define CHECK_OPTION(name, fn) \ if (strcmp(key, name) == 0) return fn; #ifndef IN3_VERSION @@ -26,7 +30,7 @@ static bool set_chainId(char* value, sb_t* conf) { } bool show_help() { - recorder_print(0, "Usage: in3 method ... \n\n%s", get_help_args()); + recorder_print(0, "Usage: " CMD_NAME " method ... \n\n%s", get_help_args()); recorder_exit(0); return true; } @@ -195,7 +199,7 @@ bool handle_option(in3_t* c, char* key, char* value, sb_t* conf, int argc, char* CHECK_OPTION("nonce", set_uint64(&get_txdata()->nonce, value)) CHECK_OPTION("wait", set_uint32(&get_txdata()->wait, "1")) CHECK_OPTION("block", set_string(&get_txdata()->block, value)) - CHECK_OPTION("block", set_data(value)) + CHECK_OPTION("data", set_data(value)) CHECK_OPTION("value", set_string(&get_txdata()->value, get_wei(value))) CHECK_OPTION("zksync.create2", set_create2(value, conf)) CHECK_OPTION("test-request", set_flag(get_weightsdata(), weight_test_request, value)) diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js index a4eb1ef9b..f726092a8 100755 --- a/scripts/generator/generate.js +++ b/scripts/generator/generate.js @@ -19,11 +19,15 @@ const doc_dir = [] const args_file = [] const zsh_file = [] const generators = [] +let cmdName = 'in3' +let sdkName = 'IN3' process.argv.slice(2).forEach(a => { if (a.startsWith('--src=')) src_dirs.push(a.substr(6)) else if (a.startsWith('--doc=')) doc_dir.push(a.substr(6)) else if (a.startsWith('--arg=')) args_file.push(a.substr(6)) else if (a.startsWith('--zsh=')) zsh_file.push(a.substr(6)) + else if (a.startsWith('--cmd=')) cmdName = a.substr(6) + else if (a.startsWith('--sdk=')) sdkName = a.substr(6) else if (a.startsWith('--gen=')) generators.push(require(a.substr(6))) else throw new Error('Invalid argument : ' + a) }) @@ -110,12 +114,12 @@ function handle_config(conf, pre, title, descr) { asArray(c.example).forEach(ex => { config_doc.push('```sh') if (typeof (ex) == 'object') - config_doc.push('> in3 ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') + config_doc.push('> ' + cmdName + ' ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') else config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') config_doc.push('```\n') if (!title) - config_doc.push('```js\nconst in3 = new IN3(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') + config_doc.push('```js\nconst ' + cmdName + ' = new ' + sdkName + '(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') }) } @@ -219,7 +223,7 @@ for (const s of Object.keys(docs).sort()) { rpc_doc.push('\n# ---- Response -----\n\n' + yaml.stringify(data)) rpc_doc.push('```\n') */ - rpc_doc.push('```sh\n> in3 ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) + rpc_doc.push('```sh\n> ' + cmdName + ' ' + (ex.cmdParams ? (ex.cmdParams + ' ') : '') + req.method + ' ' + (req.params.map(toCmdParam).join(' ').trim()) + (is_json ? ' | jq' : '')) rpc_doc.push(is_json ? JSON.stringify(data.result, null, 2) : '' + data.result) rpc_doc.push('```\n') From e97ff033e74c3ab6a873630d34de652b51dc6683 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 21 Apr 2021 13:23:20 +0200 Subject: [PATCH 142/221] add missing config-params --- c/src/pay/zksync/rpc.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 50c20d3ef..c266a4b2b 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -95,6 +95,16 @@ zksync: codehash: descr: the hash of the actual deploy-tx including the constructor-arguments. type: bytes32 + + verify_proof_method: + descr: rpc-method, which will be used to verify the incomming proof before cosigning. + type: string + cmd: zvpm + + create_proof_method: + descr: rpc-method, which will be used to create the proof needed for cosigning. + type: string + cmd: zcpm # rpc zksync_contract_address: From 6f264e5b1296f86e9356030e4eff751409bf2830 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 21 Apr 2021 14:03:02 +0200 Subject: [PATCH 143/221] add exception for zk_wallet --- c/src/pay/zksync/zksync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index 195f73b4a..f63a11e9e 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -137,7 +137,7 @@ static in3_ret_t zksync_rpc(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { // check the prefix (zksync_ or zk_ is supported) if (strncmp(ctx->method, "zksync_", 7) == 0) ctx->method += 7; - else if (strncmp(ctx->method, "zk_", 3) == 0) + else if (strncmp(ctx->method, "zk_", 3) == 0 && strncmp(ctx->method, "zk_wallet_", 10)) ctx->method += 3; else return IN3_EIGNORE; From 6625ee1a2eb0698dc542fc8dd5696000ede4b84a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 21 Apr 2021 14:07:02 +0200 Subject: [PATCH 144/221] fix typo --- c/src/core/client/rpc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index 45bb6352a..badd47e89 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -71,7 +71,7 @@ config: experimental: type: bool - descr: iif true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. + descr: if true the client allows to use use experimental features, otherwise a exception is thrown if those would be used. example: true optional: true default: false From ea4d09642c5576fd428db4d30111493d5dd77f78 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 22 Apr 2021 19:46:43 +0200 Subject: [PATCH 145/221] fixed ci --- c/ci-analyse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/ci-analyse.yml b/c/ci-analyse.yml index 11158c1a2..9ce174630 100644 --- a/c/ci-analyse.yml +++ b/c/ci-analyse.yml @@ -127,7 +127,7 @@ cpd: tags: - short-jobs script: - - cpd --minimum-tokens 180 --language cpp --exclude c/src/third-party --exclude c/src/signer/iamo-zksync/iamo_deploy.h --files c/src + - cpd --minimum-tokens 180 --language cpp --exclude c/src/third-party --exclude c/src/signer/zk_wallet/iamo_deploy.h --files c/src - cpd --minimum-tokens 150 --language java --files java/src - cpd --minimum-tokens 150 --language python --files python From 635c8d157123fe4fc2a5a942cdecd1a1deed5a39 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 22 Apr 2021 21:43:15 +0200 Subject: [PATCH 146/221] add addProperty --- java/src/in3/utils/JSON.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 7d5165d61..468f50c5e 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -266,6 +266,12 @@ public static void appendKey(StringBuilder sb, String key, Object value) { sb.append("\"").append(key).append("\":").append(toJson(value)).append(","); } + public void addProperty(StringBuilder sb, String key) { + Object o = get(key); + if (o) + sb.append(sb.length() == 1 ? "" : ",").append("\"").append(key).append("\":").append(toJson(value)); + } + @Override public int hashCode() { final int prime = 31; From edc2f11ec8076cd5a2162d69251f4848499fd36c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 14:33:56 +0200 Subject: [PATCH 147/221] added util-functions --- java/src/in3/IN3.java | 9 +++++++ java/src/in3/utils/JSON.java | 47 +++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/java/src/in3/IN3.java b/java/src/in3/IN3.java index bcfc03e7e..8f94a6ae2 100644 --- a/java/src/in3/IN3.java +++ b/java/src/in3/IN3.java @@ -70,6 +70,15 @@ private IN3(long chainAlias) { this.config = new ClientConfiguration(this.getDefaultConfig()); } + /** + * creates a client with the default config. + */ + public IN3() { + ptr = init(1); + this.config = new ClientConfiguration(this.getDefaultConfig()); + this.config.markAsSynced(); + } + /** * create a Incubed client using the chain-config. if chainId is * Chain.MULTICHAIN, the client can later be switched between different chains, diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 468f50c5e..984e20fb0 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -51,7 +51,7 @@ public class JSON { private HashMap map = new HashMap(); - private static native int key(String name); + protected static native int key(String name); JSON() {} @@ -211,6 +211,20 @@ public static int asInt(Object o) { return 0; } + public static double asDouble(Object o) { + if (o == null) + return 0; + if (o instanceof Float) return ((Float) o).doubleValue(); + if (o instanceof Double) return ((Double) o).doubleValue(); + if (o instanceof String) + return (((String) o).length() > 2 && o.toString().charAt(1) == 'x') + ? JSON.asBigInteger(o).doubleValue() + : Double.parseDouble(o.toString()); + if (o instanceof Number) + return ((Number) o).doubleValue(); + return 0; + } + public static boolean asBoolean(Object o) { if (o == null) return false; @@ -268,8 +282,12 @@ public static void appendKey(StringBuilder sb, String key, Object value) { public void addProperty(StringBuilder sb, String key) { Object o = get(key); - if (o) - sb.append(sb.length() == 1 ? "" : ",").append("\"").append(key).append("\":").append(toJson(value)); + if (o) addPropertyJson(sb, key, toJson(value)); + } + + public void addPropertyJson(StringBuilder sb, String key, String json) { + if (json) + sb.append(sb.length() == 1 ? "" : ",").append("\"").append(key).append("\":").append(json); } @Override @@ -297,4 +315,27 @@ else if (!map.equals(other.map)) return false; return true; } + + public Map asMap(java.util.function.Function converter) { + + HashMap data = new HashMap(); + for (Integer k : map.keySet()) + data.put(k, converter.apply(map.get(k))); + return new HashMap() { + @Override + public T get(Object key) { + return data.get(JSON.key((String) key)); + } + + @Override + public boolean containsKey(Object key) { + return data.containsKey(JSON.key((String) key)); + } + + @Override + public T put(String key, T value) { + return data.put(JSON.key((String) key), value); + } + }; + } } From 7397fdee7c352143b30390513ff1bb4bb0c1fa93 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 14:40:56 +0200 Subject: [PATCH 148/221] fix java-error --- java/src/in3/utils/JSON.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 984e20fb0..ec6238f49 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -282,11 +282,11 @@ public static void appendKey(StringBuilder sb, String key, Object value) { public void addProperty(StringBuilder sb, String key) { Object o = get(key); - if (o) addPropertyJson(sb, key, toJson(value)); + if (o != null) addPropertyJson(sb, key, toJson(value)); } public void addPropertyJson(StringBuilder sb, String key, String json) { - if (json) + if (json != null) sb.append(sb.length() == 1 ? "" : ",").append("\"").append(key).append("\":").append(json); } From 35388ddba6dc5c7aa4626c5d00a986ddea251ce1 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 14:44:47 +0200 Subject: [PATCH 149/221] fix java --- java/src/in3/utils/JSON.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index ec6238f49..e8ebadbaf 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -282,7 +282,7 @@ public static void appendKey(StringBuilder sb, String key, Object value) { public void addProperty(StringBuilder sb, String key) { Object o = get(key); - if (o != null) addPropertyJson(sb, key, toJson(value)); + if (o != null) addPropertyJson(sb, key, JSON.toJson(value)); } public void addPropertyJson(StringBuilder sb, String key, String json) { From a3a7023aecb316233d199b10a834b4dbc61b5db8 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 14:49:19 +0200 Subject: [PATCH 150/221] fixed toJSON --- java/src/in3/utils/JSON.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index e8ebadbaf..1df224a89 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -282,7 +282,7 @@ public static void appendKey(StringBuilder sb, String key, Object value) { public void addProperty(StringBuilder sb, String key) { Object o = get(key); - if (o != null) addPropertyJson(sb, key, JSON.toJson(value)); + if (o != null) addPropertyJson(sb, key, JSON.toJson(o)); } public void addPropertyJson(StringBuilder sb, String key, String json) { From 1f05ec6a84e18106359a0a549e20ebe82638e217 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 15:06:47 +0200 Subject: [PATCH 151/221] fix JSON --- java/src/in3/utils/JSON.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 1df224a89..0135e13c2 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -318,7 +318,7 @@ else if (!map.equals(other.map)) public Map asMap(java.util.function.Function converter) { - HashMap data = new HashMap(); + final HashMap data = new HashMap(); for (Integer k : map.keySet()) data.put(k, converter.apply(map.get(k))); return new HashMap() { From 3e9abaa36a28e6600eb442f0174551beac6398f7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 16:50:40 +0200 Subject: [PATCH 152/221] fix java-version issue --- java/src/CMakeLists.txt | 1 + java/src/in3/utils/Converter.java | 48 +++++++++++++++++++++++++++++++ java/src/in3/utils/JSON.java | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 java/src/in3/utils/Converter.java diff --git a/java/src/CMakeLists.txt b/java/src/CMakeLists.txt index e7d16af5e..a9e777b5f 100644 --- a/java/src/CMakeLists.txt +++ b/java/src/CMakeLists.txt @@ -83,6 +83,7 @@ IF (NOT DEFINED ANDROID_ABI) in3/utils/Account.java in3/utils/Crypto.java in3/utils/JSON.java + in3/utils/Converter.java in3/utils/Signature.java in3/utils/SignatureType.java in3/utils/Signer.java diff --git a/java/src/in3/utils/Converter.java b/java/src/in3/utils/Converter.java new file mode 100644 index 000000000..229e57aa0 --- /dev/null +++ b/java/src/in3/utils/Converter.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +package in3.utils; + +/** + * a Interface for converting values. + */ +public interface Converter { + /** + * Applies this function to the given argument. + * + * @param t the function argument + * @return the function result + */ + R apply(T t); +} diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 0135e13c2..79d54f17f 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -316,7 +316,7 @@ else if (!map.equals(other.map)) return true; } - public Map asMap(java.util.function.Function converter) { + public Map asMap(Converter converter) { final HashMap data = new HashMap(); for (Integer k : map.keySet()) From 0b77d3fa561320ebb5f174a252a6792c4b93c30f Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 17:39:33 +0200 Subject: [PATCH 153/221] fix rust CI --- rust/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ci.yml b/rust/ci.yml index e11ca4919..9ba279a16 100644 --- a/rust/ci.yml +++ b/rust/ci.yml @@ -94,8 +94,8 @@ rust_valgrind: - export CARGO_MANIFEST_DIR=. - export IN3_MODE="DEBUG" - printf "{\n ignore_libcrypto_conditional_jump_errors\n Memcheck:Leak\n ...\n obj:*/libcrypto.so.*\n}\n" > suppress.valgrind - - export IN3_EXEC="`basename target/debug/in3-*`" - - valgrind $VALGRIND_OPTS target/debug/$IN3_EXEC test_eth_api + - export IN3_EXEC="`ls target/debug/deps/in3-* | grep -v "\.d" | xargs basename`" + - valgrind $VALGRIND_OPTS target/debug/deps/$IN3_EXEC test_eth_api tags: - long-jobs From 550df4bb734acf25ba45c6fbc4e35f70e3b5ac40 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 19:04:54 +0200 Subject: [PATCH 154/221] fix rpc for string[] --- c/src/pay/zksync/rpc.yml | 3 ++- java/src/in3/utils/JSON.java | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index c266a4b2b..98f2fadd1 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -77,7 +77,8 @@ zksync: musig_urls: descr: a array of strings with urls based on the `musig_pub_keys`. It is used so generate the combined signature by exchaing signature data (commitment and signatureshares) if the local client does not hold this key. - type: string[] + type: string + array: true optional: true cmd: zmu diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 79d54f17f..003eb9e26 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -53,7 +53,7 @@ public class JSON { protected static native int key(String name); - JSON() {} + public JSON() {} /** * gets the property @@ -109,6 +109,16 @@ public long getLong(String key /** the propertyName */ return asLong(get(key)); } + /** + * returns the property as double + * + * @return the long value + */ + public double getDouble(String key /** the propertyName */ + ) { + return asDouble(get(key)); + } + /** * returns the property as BigInteger * From 702c6f714295ffae7ca926015f0b9eeae5cb4404 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 19:28:18 +0200 Subject: [PATCH 155/221] fixed equs name for cmd tests --- c/test/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/c/test/CMakeLists.txt b/c/test/CMakeLists.txt index d279ae023..ad287dd15 100644 --- a/c/test/CMakeLists.txt +++ b/c/test/CMakeLists.txt @@ -114,13 +114,17 @@ foreach (file ${files}) endforeach () +if ( NOT CMD_NAME ) + set(CMD_NAME in3) +endif () + # add cmd--tests file(GLOB files "testdata/cmd/*.txt") foreach (file ${files}) get_filename_component(testname "${file}" NAME_WE) add_test( NAME "cmd_${testname}" - COMMAND ${CMAKE_BINARY_DIR}/bin/in3 -fi ${file} + COMMAND ${CMAKE_BINARY_DIR}/bin/${CMD_NAME} -fi ${file} WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/.. ) set_tests_properties("cmd_${testname}" PROPERTIES From ef5fbb8af8ff138ef1ed898352ed6ac21833e839 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 19:55:46 +0200 Subject: [PATCH 156/221] fix reqadthedocs --- c/ci-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/ci-deploy.yml b/c/ci-deploy.yml index e818bad61..be827e6c7 100644 --- a/c/ci-deploy.yml +++ b/c/ci-deploy.yml @@ -63,7 +63,7 @@ readthedocs: - chmod 777 bin/* - cd ../wasm/src - cp ../../in3_wasm/index.d.ts . - - npm --cache .npm i typedoc + - npm i typedoc - node_modules/.bin/typedoc --includeDeclarations --ignoreCompilerErrors --readme none --target ES6 --mode 'modules' --excludeExternals --json doc.json index.d.ts - cat doc.json | ../../generator/bin/slockit-docu index.d blockchainsllc/in3/blob/master/wasm/src "$PRE_DOC" > ../../doc/docs/api-wasm.md - cd ../../doc/docs && make html && make latexpdf && make text From 149608e7057e1ea381edcb1b6f3a908519ca0f90 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 21:37:29 +0200 Subject: [PATCH 157/221] fix typedoc --- c/ci-deploy.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/c/ci-deploy.yml b/c/ci-deploy.yml index be827e6c7..19a29091a 100644 --- a/c/ci-deploy.yml +++ b/c/ci-deploy.yml @@ -63,8 +63,7 @@ readthedocs: - chmod 777 bin/* - cd ../wasm/src - cp ../../in3_wasm/index.d.ts . - - npm i typedoc - - node_modules/.bin/typedoc --includeDeclarations --ignoreCompilerErrors --readme none --target ES6 --mode 'modules' --excludeExternals --json doc.json index.d.ts + - typedoc --includeDeclarations --ignoreCompilerErrors --readme none --target ES6 --mode 'modules' --excludeExternals --json doc.json index.d.ts - cat doc.json | ../../generator/bin/slockit-docu index.d blockchainsllc/in3/blob/master/wasm/src "$PRE_DOC" > ../../doc/docs/api-wasm.md - cd ../../doc/docs && make html && make latexpdf && make text artifacts: From 92e8af23ffdd8adc6fc7d2067b0758a0ed68e22c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 22:56:12 +0200 Subject: [PATCH 158/221] fix rtd --- c/ci-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/ci-deploy.yml b/c/ci-deploy.yml index 19a29091a..a172d596e 100644 --- a/c/ci-deploy.yml +++ b/c/ci-deploy.yml @@ -65,7 +65,7 @@ readthedocs: - cp ../../in3_wasm/index.d.ts . - typedoc --includeDeclarations --ignoreCompilerErrors --readme none --target ES6 --mode 'modules' --excludeExternals --json doc.json index.d.ts - cat doc.json | ../../generator/bin/slockit-docu index.d blockchainsllc/in3/blob/master/wasm/src "$PRE_DOC" > ../../doc/docs/api-wasm.md - - cd ../../doc/docs && make html && make latexpdf && make text + - cd ../../doc/docs && make html && make text artifacts: paths: - doc/build From 8a3ae7be2ed029bf620105f08ae604506231f095 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 23 Apr 2021 23:18:16 +0200 Subject: [PATCH 159/221] clear cache before running mactests --- python/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ci.yml b/python/ci.yml index 05bdacbc2..f7edfa699 100644 --- a/python/ci.yml +++ b/python/ci.yml @@ -113,6 +113,7 @@ python_macos: before_script: - *cache_scipt_before script: + - rm -rf ~/.in3 || echo "could not delete cache" - cd python_multilib - pip3 install --upgrade pip - pip3 install -r requirements.txt From 27c0d9fea5674141887489f6345310c95d8e0e52 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 24 Apr 2021 10:30:18 +0200 Subject: [PATCH 160/221] fix javadoc --- java/src/in3/eth1/Block.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/src/in3/eth1/Block.java b/java/src/in3/eth1/Block.java index 877e850dc..878e445c8 100644 --- a/java/src/in3/eth1/Block.java +++ b/java/src/in3/eth1/Block.java @@ -151,8 +151,6 @@ public String[] getTransactionHashes() { /** * the transactions of the block. - * - * @throws if the Transactions are not available */ public Transaction[] getTransactions() throws Exception { Object[] tx = (Object[]) data.get("transactions"); From 8dfa13ec4cef5b55fb8e8965bd7e08a0304292fc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 24 Apr 2021 13:08:44 +0200 Subject: [PATCH 161/221] update generator --- scripts/generator/generate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js index f726092a8..07ffec6ac 100755 --- a/scripts/generator/generate.js +++ b/scripts/generator/generate.js @@ -116,7 +116,7 @@ function handle_config(conf, pre, title, descr) { if (typeof (ex) == 'object') config_doc.push('> ' + cmdName + ' ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') else - config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') + config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> ' + cmdName + ' ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') config_doc.push('```\n') if (!title) config_doc.push('```js\nconst ' + cmdName + ' = new ' + sdkName + '(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') From af15db5bb7b0fd8f6c47ee599c0839f2d0f6a8cb Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Sat, 24 Apr 2021 14:44:29 +0200 Subject: [PATCH 162/221] add cmake option descr --- c/macro.cmake | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/c/macro.cmake b/c/macro.cmake index 0413cc2ed..7278d8989 100644 --- a/c/macro.cmake +++ b/c/macro.cmake @@ -1,9 +1,13 @@ macro(add_static_library ) - cmake_parse_arguments(_LIB "" "NAME;REGISTER" "SOURCES;DEPENDS" ${ARGN} ) - string(TOUPPER "MOD_${_LIB_NAME}" tmp) - option(${tmp} "module ${_LIB_NAME}" ON) - if (${${tmp}}) + cmake_parse_arguments(_LIB "" "NAME;REGISTER;OPTION;DESCR" "SOURCES;DEPENDS" ${ARGN} ) + if (_LIB_OPTION) + option(${_LIB_OPTION} ${_LIB_DESCR} ON) + else() + string(TOUPPER "MOD_${_LIB_NAME}" _LIB_OPTION) + set(${_LIB_OPTION} ON) + endif() + if (${${_LIB_OPTION}}) # create objects add_library(${_LIB_NAME}_o OBJECT ${_LIB_SOURCES}) From 174482e2b615e17bc95be1b3ddd39a084e0319dc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 30 Apr 2021 09:19:23 +0200 Subject: [PATCH 163/221] update generator --- scripts/generator/generate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js index f726092a8..07ffec6ac 100755 --- a/scripts/generator/generate.js +++ b/scripts/generator/generate.js @@ -116,7 +116,7 @@ function handle_config(conf, pre, title, descr) { if (typeof (ex) == 'object') config_doc.push('> ' + cmdName + ' ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') else - config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> in3 ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') + config_doc.push([...asArray(c.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> ' + cmdName + ' ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') config_doc.push('```\n') if (!title) config_doc.push('```js\nconst ' + cmdName + ' = new ' + sdkName + '(' + JSON.stringify({ [key]: ex }, null, 2) + ')\n```\n') From da9614fdffe79e121d89b08438e1bdec26631f0d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 30 Apr 2021 09:22:01 +0200 Subject: [PATCH 164/221] fixed warning --- c/src/third-party/zkcrypto/wasm/lib.c | 59 ++++++++++----------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/c/src/third-party/zkcrypto/wasm/lib.c b/c/src/third-party/zkcrypto/wasm/lib.c index 6325b5844..e7122ca34 100644 --- a/c/src/third-party/zkcrypto/wasm/lib.c +++ b/c/src/third-party/zkcrypto/wasm/lib.c @@ -20,8 +20,6 @@ void (*Z___wbindgen_placeholder__Z___wbg_error_4bb6c2a97407129aZ_vii)(u32, u32); /* import: './web.js' '__wbindgen_object_drop_ref' */ void (*Z___wbindgen_placeholder__Z___wbindgen_object_drop_refZ_vi)(u32); - - /* import: '__wbindgen_placeholder__' '__wbindgen_string_new' */ u32 (*Z___wbindgen_placeholder__Z___wbindgen_string_newZ_iii)(u32, u32); /* import: '__wbindgen_placeholder__' '__wbindgen_throw' */ @@ -32,8 +30,6 @@ void (*Z___wbindgen_placeholder__Z___wbindgen_rethrowZ_vi)(u32); /* import: '__wbindgen_placeholder__' '__wbindgen_debug_string' */ void (*Z___wbindgen_placeholder__Z___wbindgen_debug_stringZ_vii)(u32, u32); - - #define wmalloc(l) zkcrypto_Z___wbindgen_mallocZ_ii(l) #define wfree(p, l) zkcrypto_Z___wbindgen_freeZ_vii(p, l) #define mem_ptr(p) (zkcrypto_Z_memory->data + (p)) @@ -75,23 +71,21 @@ void zke_drop(u32 a) { /* import: '__wbindgen_placeholder__' '__wbindgen_string_new' */ u32 zke_string_new(u32 a, u32 b) { printf("# zke_string_new\n"); - u32 sp = wmalloc(b+1); - memcpy(mem_ptr(sp),mem_ptr(a),b+1); - char* s = (void*)mem_ptr(sp); - s[b]=0; + u32 sp = wmalloc(b + 1); + memcpy(mem_ptr(sp), mem_ptr(a), b + 1); + char* s = (void*) mem_ptr(sp); + s[b] = 0; return sp; } /* import: '__wbindgen_placeholder__' '__wbindgen_throw' */ void zke_throw(u32 a, u32 b) { if (a || b) - printf("# zke_throw\n"); - + printf("# zke_throw\n"); } /* import: '__wbindgen_placeholder__' '__wbindgen_rethrow' */ void zke_rethrow(u32 x) { if (x) - printf("# zke_rethrow\n"); - + printf("# zke_rethrow\n"); } void zkcrypto_initialize() { @@ -107,17 +101,15 @@ void zkcrypto_initialize() { Z___wbindgen_placeholder__Z___wbindgen_object_drop_refZ_vi = zke_drop; /* import: '__wbindgen_placeholder__' '__wbindgen_string_new' */ - Z___wbindgen_placeholder__Z___wbindgen_string_newZ_iii= zke_string_new; + Z___wbindgen_placeholder__Z___wbindgen_string_newZ_iii = zke_string_new; /* import: '__wbindgen_placeholder__' '__wbindgen_throw' */ Z___wbindgen_placeholder__Z___wbindgen_throwZ_vii = zke_throw; /* import: '__wbindgen_placeholder__' '__wbindgen_rethrow' */ Z___wbindgen_placeholder__Z___wbindgen_rethrowZ_vi = zke_rethrow; /* import: '__wbindgen_placeholder__' '__wbindgen_debug_string' */ Z___wbindgen_placeholder__Z___wbindgen_debug_stringZ_vii = zke_debug_string; - } - in3_ret_t zkcrypto_pk_from_seed(bytes_t seed, bytes32_t dst) { u32 sp = wmalloc(seed.len); memcpy(mem_ptr(sp), seed.data, seed.len); @@ -150,7 +142,6 @@ in3_ret_t zkcrypto_pk_to_pubkey_hash(bytes32_t pk, uint8_t* dst) { return r1 == 20 ? IN3_OK : IN3_EINVAL; } - in3_ret_t zkcrypto_sign_musig(bytes32_t pk, bytes_t msg, uint8_t* dst) { u32 pkp = wmalloc(32); u32 mp = wmalloc(msg.len); @@ -182,13 +173,13 @@ zkcrypto_signer_t zkcrypto_signer_new(bytes_t pub_keys, uint32_t pos) { } void zkcrypto_signer_free(zkcrypto_signer_t signer) { - return zkcrypto_Z___wbg_musigbn256wasmsigner_freeZ_vi((u32) signer); + return zkcrypto_Z___wbg_musigbn256wasmsigner_freeZ_vi((u32)(uint64_t) signer); } in3_ret_t zkcrypto_signer_compute_precommitment(zkcrypto_signer_t signer, bytes_t seed, uint8_t* dst) { u32 data = wmalloc(seed.len); memcpy(mem_ptr(data), seed.data, seed.len); - zkcrypto_Z_musigbn256wasmsigner_compute_precommitmentZ_viiii(8, (u32) signer, data, seed.len/4); + zkcrypto_Z_musigbn256wasmsigner_compute_precommitmentZ_viiii(8, (u32)(uint64_t) signer, data, seed.len / 4); u32 r0 = mem_u32(2); u32 r1 = mem_u32(3); if (r1 == 32) memcpy(dst, mem_ptr(r0), r1); @@ -196,11 +187,10 @@ in3_ret_t zkcrypto_signer_compute_precommitment(zkcrypto_signer_t signer, bytes_ return r1 == 32 ? IN3_OK : IN3_EINVAL; } - in3_ret_t zkcrypto_signer_receive_precommitment(zkcrypto_signer_t signer, bytes_t input, uint8_t* dst) { u32 data = wmalloc(input.len); memcpy(mem_ptr(data), input.data, input.len); - zkcrypto_Z_musigbn256wasmsigner_receive_precommitmentsZ_viiii(8, (u32) signer, data, input.len); + zkcrypto_Z_musigbn256wasmsigner_receive_precommitmentsZ_viiii(8, (u32)(uint64_t) signer, data, input.len); u32 r0 = mem_u32(2); u32 r1 = mem_u32(3); if (r1 == 32) memcpy(dst, mem_ptr(r0), r1); @@ -208,11 +198,10 @@ in3_ret_t zkcrypto_signer_receive_precommitment(zkcrypto_signer_t signer, bytes_ return r1 == 32 ? IN3_OK : IN3_EINVAL; } - in3_ret_t zkcrypto_signer_receive_commitment(zkcrypto_signer_t signer, bytes_t input, uint8_t* dst) { u32 data = wmalloc(input.len); memcpy(mem_ptr(data), input.data, input.len); - zkcrypto_Z_musigbn256wasmsigner_receive_commitmentsZ_viiii(8, (u32) signer, data, input.len); + zkcrypto_Z_musigbn256wasmsigner_receive_commitmentsZ_viiii(8, (u32)(uint64_t) signer, data, input.len); u32 r0 = mem_u32(2); u32 r1 = mem_u32(3); if (r1 == 32) memcpy(dst, mem_ptr(r0), r1); @@ -220,30 +209,28 @@ in3_ret_t zkcrypto_signer_receive_commitment(zkcrypto_signer_t signer, bytes_t i return r1 == 32 ? IN3_OK : IN3_EINVAL; } - - in3_ret_t zkcrypto_signer_sign(zkcrypto_signer_t signer, bytes32_t pk, bytes_t input, uint8_t* dst) { u32 data = wmalloc(input.len); memcpy(mem_ptr(data), input.data, input.len); u32 pkey = wmalloc(32); memcpy(mem_ptr(pkey), pk, 32); - zkcrypto_Z_musigbn256wasmsigner_signZ_viiiiii(8, (u32) signer, pkey, 32,data, input.len); + zkcrypto_Z_musigbn256wasmsigner_signZ_viiiiii(8, (u32)(uint64_t) signer, pkey, 32, data, input.len); u32 r0 = mem_u32(2); u32 r1 = mem_u32(3); - if (r1==32) memcpy(dst, mem_ptr(r0), r1); + if (r1 == 32) memcpy(dst, mem_ptr(r0), r1); wfree(r0, r1); - return r1 ==32 ? IN3_OK : IN3_EINVAL; + return r1 == 32 ? IN3_OK : IN3_EINVAL; } -in3_ret_t zkcrypto_signer_receive_signature_shares(zkcrypto_signer_t signer, bytes_t input, uint8_t* dst) { +in3_ret_t zkcrypto_signer_receive_signature_shares(zkcrypto_signer_t signer, bytes_t input, uint8_t* dst) { u32 data = wmalloc(input.len); memcpy(mem_ptr(data), input.data, input.len); - zkcrypto_Z_musigbn256wasmsigner_receive_signature_sharesZ_viiii(8, (u32) signer, data, input.len); + zkcrypto_Z_musigbn256wasmsigner_receive_signature_sharesZ_viiii(8, (u32)(uint64_t) signer, data, input.len); u32 r0 = mem_u32(2); u32 r1 = mem_u32(3); - if (r1==64) memcpy(dst, mem_ptr(r0), r1); + if (r1 == 64) memcpy(dst, mem_ptr(r0), r1); wfree(r0, r1); - return r1==64 ? IN3_OK : IN3_EINVAL; + return r1 == 64 ? IN3_OK : IN3_EINVAL; } bool zkcrypto_verify_signatures(bytes_t message, bytes_t pubkeys, bytes_t signature) { @@ -253,10 +240,9 @@ bool zkcrypto_verify_signatures(bytes_t message, bytes_t pubkeys, bytes_t signat memcpy(mem_ptr(_pubkeys), pubkeys.data, pubkeys.len); u32 _signature = wmalloc(signature.len); memcpy(mem_ptr(_signature), signature.data, signature.len); - return zkcrypto_Z_musigbn256wasmverifier_verifyZ_iiiiiii(_message, message.len, _pubkeys,pubkeys.len, _signature,signature.len)!=0; + return zkcrypto_Z_musigbn256wasmverifier_verifyZ_iiiiiii(_message, message.len, _pubkeys, pubkeys.len, _signature, signature.len) != 0; } - in3_ret_t zkcrypto_pubkey_hash(bytes_t pubkey, uint8_t* dst) { u32 pk = wmalloc(pubkey.len); memcpy(mem_ptr(pk), pubkey.data, pubkey.len); @@ -268,13 +254,10 @@ in3_ret_t zkcrypto_pubkey_hash(bytes_t pubkey, uint8_t* dst) { return r1 == 20 ? IN3_OK : IN3_EINVAL; } - - -bool zkcrypto_verify_musig(bytes_t message, bytes_t signature) { +bool zkcrypto_verify_musig(bytes_t message, bytes_t signature) { u32 _message = wmalloc(message.len); memcpy(mem_ptr(_message), message.data, message.len); u32 _signature = wmalloc(signature.len); memcpy(mem_ptr(_signature), signature.data, signature.len); - return zkcrypto_Z_verify_musigZ_iiiii(_message, message.len, _signature,signature.len)!=0; + return zkcrypto_Z_verify_musigZ_iiiii(_message, message.len, _signature, signature.len) != 0; } - From b258dca5da8a3fc44c771a6578887a12eb7a1615 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 6 May 2021 08:43:29 +0200 Subject: [PATCH 165/221] fix call in cmd --- c/src/cmd/in3/rpc_handler.c | 4 ++-- c/src/cmd/in3/tx.c | 4 ++-- c/src/cmd/in3/tx.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/c/src/cmd/in3/rpc_handler.c b/c/src/cmd/in3/rpc_handler.c index 008eea2ff..7308c7a48 100644 --- a/c/src/cmd/in3/rpc_handler.c +++ b/c/src/cmd/in3/rpc_handler.c @@ -16,12 +16,12 @@ static bool decode_keystore(char* args, int argc, char** argv) { return true; } static bool _call(in3_t* c, char** method, sb_t* params) { - encode_abi(c, params); + encode_abi(c, params, true); *method = "eth_call"; return false; } static bool _send(in3_t* c, char** method, sb_t* params) { - encode_abi(c, params); + encode_abi(c, params, false); if (is_onlyshow_rawtx() && (c->plugin_acts & (PLGN_ACT_SIGN | PLGN_ACT_SIGN_ACCOUNT)) == 0) *method = "in3_prepareTx"; else diff --git a/c/src/cmd/in3/tx.c b/c/src/cmd/in3/tx.c index fd2b73e4d..4220264f0 100644 --- a/c/src/cmd/in3/tx.c +++ b/c/src/cmd/in3/tx.c @@ -78,6 +78,6 @@ static abi_sig_t* prepare_tx(char* fn_sig, char* to, sb_t* args, char* block_num return req; } -void encode_abi(in3_t* c, sb_t* args) { - _tx.abi_sig = prepare_tx(_tx.sig, resolve(c, _tx.to), args, _tx.block, _tx.gas, _tx.gas_price, _tx.value, _tx.data, _tx.from); +void encode_abi(in3_t* c, sb_t* args, bool with_block) { + _tx.abi_sig = prepare_tx(_tx.sig, resolve(c, _tx.to), args, _tx.block == NULL && with_block ? "latest" : _tx.block, _tx.gas, _tx.gas_price, _tx.value, _tx.data, _tx.from); } \ No newline at end of file diff --git a/c/src/cmd/in3/tx.h b/c/src/cmd/in3/tx.h index 6b3a7a0e4..0c7f7d9d8 100644 --- a/c/src/cmd/in3/tx.h +++ b/c/src/cmd/in3/tx.h @@ -17,4 +17,4 @@ typedef struct tx { } tx_t; tx_t* get_txdata(); -void encode_abi(in3_t* c, sb_t* args); \ No newline at end of file +void encode_abi(in3_t* c, sb_t* args, bool with_block); \ No newline at end of file From 5ef363ea9ff5f2d7d835f7ea26d9f9fe03790640 Mon Sep 17 00:00:00 2001 From: jbentke Date: Mon, 10 May 2021 12:15:40 +0200 Subject: [PATCH 166/221] changed difficulty to double --- c/src/verifier/btc/rpc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 9d8878fad..ffb961650 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -32,7 +32,7 @@ types: type: bytes4 difficulty: descr: The difficulty - type: uint256 + type: double chainwork: descr: Expected number of hashes required to produce the current chain (in hex) type: hex From 75d26cff1dfa74fc85cb46cf230db6c757b6a7dc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 10 May 2021 14:20:47 +0200 Subject: [PATCH 167/221] fix autoregister.h --- c/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt index 9306cc118..6ccf7e9d8 100644 --- a/c/CMakeLists.txt +++ b/c/CMakeLists.txt @@ -63,6 +63,8 @@ IF (TRANSPORTS AND NOT SWIFT) add_subdirectory(src/transport) ENDIF (TRANSPORTS AND NOT SWIFT) +ADD_DEFINITIONS("-DIN3_AUTOINIT_PATH=\"${CMAKE_BINARY_DIR}/autoregister.h\"") + add_subdirectory(src/core) add_subdirectory(src/init) add_subdirectory(src/verifier) @@ -80,7 +82,7 @@ foreach(m IN LISTS modules) set(REGISTER_DEF "${REGISTER_DEF}in3_ret_t ${m} (in3_t*);\n") set(REGISTER_CALL "${REGISTER_CALL} in3_register_default(${m});\n") endforeach() -file(WRITE src/init/autoregister.h "${REGISTER_DEF}\n\nstatic void auto_init() {\n${REGISTER_CALL}}\n") +file(WRITE ${CMAKE_BINARY_DIR}/autoregister.h "${REGISTER_DEF}\n\nstatic void auto_init() {\n${REGISTER_CALL}}\n") # define lib dir link_directories(${CMAKE_BINARY_DIR}/lib/) From 025fda75d46b697aba981baf1187181566c629e6 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 10 May 2021 14:47:17 +0200 Subject: [PATCH 168/221] fixed year --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8d9072cf3..9065f4aab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # This file is part of the Incubed project. # Sources: https://github.com/blockchainsllc/in3 # -# Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC +# Copyright (C) 2018-2021 slock.it GmbH, Blockchains LLC # # # COMMERCIAL LICENSE USAGE From 4d3b99f7343e160fe43e48096d0ba4245963b06b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 11 May 2021 12:09:51 +0200 Subject: [PATCH 169/221] added core_api --- c/include/in3/core_api.h | 60 +++++++++++++ c/src/api/CMakeLists.txt | 3 +- c/src/api/core/CMakeLists.txt | 45 ++++++++++ c/src/api/core/core_api.c | 159 ++++++++++++++++++++++++++++++++++ c/src/api/core/core_api.h | 60 +++++++++++++ c/src/api/core/rpc.yml | 74 ++++++++++++++++ c/src/api/eth1/rpc.yml | 72 --------------- c/src/api/eth1/rpc_api.c | 95 -------------------- 8 files changed, 400 insertions(+), 168 deletions(-) create mode 100644 c/include/in3/core_api.h create mode 100644 c/src/api/core/CMakeLists.txt create mode 100644 c/src/api/core/core_api.c create mode 100644 c/src/api/core/core_api.h create mode 100644 c/src/api/core/rpc.yml diff --git a/c/include/in3/core_api.h b/c/include/in3/core_api.h new file mode 100644 index 000000000..90a084ac0 --- /dev/null +++ b/c/include/in3/core_api.h @@ -0,0 +1,60 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +// @PUBLIC_HEADER +/** @file + * Ethereum API. + * + * This header-file defines easy to use function, which are preparing the JSON-RPC-Request, which is then executed and verified by the incubed-client. + * */ + +#ifndef CORE_API_H +#define CORE_API_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "client.h" +#include "api_utils.h" + +/** + * register core-api + */ +in3_ret_t in3_register_core_api(in3_t* c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/api/CMakeLists.txt b/c/src/api/CMakeLists.txt index f69538abc..cd8eb20d6 100644 --- a/c/src/api/CMakeLists.txt +++ b/c/src/api/CMakeLists.txt @@ -32,9 +32,10 @@ # with this program. If not, see . ############################################################################### +add_subdirectory(utils) +add_subdirectory(core) IF (IN3API) - add_subdirectory(utils) add_subdirectory(eth1) if (NOT WASM) diff --git a/c/src/api/core/CMakeLists.txt b/c/src/api/core/CMakeLists.txt new file mode 100644 index 000000000..0fe7eb44a --- /dev/null +++ b/c/src/api/core/CMakeLists.txt @@ -0,0 +1,45 @@ +############################################################################### +# This file is part of the Incubed project. +# Sources: https://github.com/blockchainsllc/in3 +# +# Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC +# +# +# COMMERCIAL LICENSE USAGE +# +# Licensees holding a valid commercial license may use this file in accordance +# with the commercial license agreement provided with the Software or, alternatively, +# in accordance with the terms contained in a written agreement between you and +# slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further +# information please contact slock.it at in3@slock.it. +# +# Alternatively, this file may be used under the AGPL license as follows: +# +# AGPL LICENSE USAGE +# +# This program is free software: you can redistribute it and/or modify it under the +# terms of the GNU Affero General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +# [Permissions of this strong copyleft license are conditioned on making available +# complete source code of licensed works and modifications, which include larger +# works using a licensed work, under the same license. Copyright and license notices +# must be preserved. Contributors provide an express grant of patent rights.] +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +############################################################################### + + +add_static_library( + NAME core_api + REGISTER in3_register_core_api + OPTION "registers a chain independend rpc-methods util-functions" + SOURCES + core_api.c + + DEPENDS + api_utils +) diff --git a/c/src/api/core/core_api.c b/c/src/api/core/core_api.c new file mode 100644 index 000000000..03af231eb --- /dev/null +++ b/c/src/api/core/core_api.c @@ -0,0 +1,159 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +#include "../../core/client/keys.h" +#include "../../core/client/plugin.h" +#include "../../core/client/request_internal.h" +#include "../../core/client/version.h" +#include "../../core/util/debug.h" +#include "../../core/util/log.h" +#include "../../core/util/mem.h" +#include "../../third-party/crypto/rand.h" +#include "../../third-party/crypto/secp256k1.h" +#include +#include +#include +#include +#include + + +static in3_ret_t in3_sha3(in3_rpc_handle_ctx_t* ctx) { + if (!ctx->params || d_len(ctx->params) != 1) return req_set_error(ctx->req, "no data", IN3_EINVAL); + bytes32_t hash; + keccak(d_to_bytes(ctx->params + 1), hash); + return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); +} +static in3_ret_t in3_sha256(in3_rpc_handle_ctx_t* ctx) { + if (!ctx->params || d_len(ctx->params) != 1) return req_set_error(ctx->req, "no data", IN3_EINVAL); + bytes32_t hash; + bytes_t data = d_to_bytes(ctx->params + 1); + SHA256_CTX c; + sha256_Init(&c); + sha256_Update(&c, data.data, data.len); + sha256_Final(&c, hash); + return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); +} +static in3_ret_t web3_clientVersion(in3_rpc_handle_ctx_t* ctx) { + // for local chains, we return the client version of rpc endpoint. + return ctx->req->client->chain.chain_id == CHAIN_ID_LOCAL + ? IN3_EIGNORE + : in3_rpc_handle_with_string(ctx, "\"Incubed/" IN3_VERSION "\""); +} + +static in3_ret_t in3_config(in3_rpc_handle_ctx_t* ctx) { + if (!ctx->params || d_len(ctx->params) != 1 || d_type(ctx->params + 1) != T_OBJECT) return req_set_error(ctx->req, "no valid config-object as argument", IN3_EINVAL); + + ctx->req->client->pending--; // we need to to temporarly decrees it in order to allow configuring + str_range_t r = d_to_json(ctx->params + 1); + char old = r.data[r.len]; + r.data[r.len] = 0; + char* ret = in3_configure(ctx->req->client, r.data); + r.data[r.len] = old; + ctx->req->client->pending++; + + if (ret) { + req_set_error(ctx->req, ret, IN3_ECONFIG); + free(ret); + return IN3_ECONFIG; + } + + return in3_rpc_handle_with_string(ctx, "true"); +} + +static in3_ret_t in3_getConfig(in3_rpc_handle_ctx_t* ctx) { + char* ret = in3_get_config(ctx->req->client); + in3_rpc_handle_with_string(ctx, ret); + _free(ret); + return IN3_OK; +} + +static in3_ret_t in3_cacheClear(in3_rpc_handle_ctx_t* ctx) { + TRY(in3_plugin_execute_first(ctx->req, PLGN_ACT_CACHE_CLEAR, NULL)); + return in3_rpc_handle_with_string(ctx, "true"); +} + +static in3_ret_t in3_createKey(in3_rpc_handle_ctx_t* ctx) { + bytes32_t hash; + FILE* r = NULL; + if (d_len(ctx->params) == 1) { + CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) + keccak(d_to_bytes(ctx->params + 1), hash); + srand(bytes_to_int(hash, 4)); + } + else { +#ifndef WASM + r = fopen("/dev/urandom", "r"); + if (r) { + for (int i = 0; i < 32; i++) hash[i] = (uint8_t) fgetc(r); + fclose(r); + } + else +#endif + srand(current_ms() % 0xFFFFFFFF); + } + + if (!r) { +#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) + unsigned int number; + for (int i = 0; i < 32; i++) { + hash[i] = (rand_s(&number) ? rand() : (int) number) % 256; + } +#else + for (int i = 0; i < 32; i++) hash[i] = rand() % 256; +#endif + } + return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); +} + + +static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugin_ctx) { + UNUSED_VAR(pdata); + UNUSED_VAR(action); + + in3_rpc_handle_ctx_t* ctx = plugin_ctx; + TRY_RPC("web3_sha3", in3_sha3(ctx)) + TRY_RPC("keccak", in3_sha3(ctx)) + TRY_RPC("sha256", in3_sha256(ctx)) + TRY_RPC("web3_clientVersion", web3_clientVersion(ctx)) + TRY_RPC("in3_config", in3_config(ctx)) + TRY_RPC("in3_getConfig", in3_getConfig(ctx)) + TRY_RPC("in3_cacheClear", in3_cacheClear(ctx)) + TRY_RPC("in3_createKey", in3_createKey(ctx)) + + return IN3_EIGNORE; +} + +in3_ret_t in3_register_core_api(in3_t* c) { + return in3_plugin_register(c, PLGN_ACT_RPC_HANDLE, handle_intern, NULL, false); +} diff --git a/c/src/api/core/core_api.h b/c/src/api/core/core_api.h new file mode 100644 index 000000000..a281b4598 --- /dev/null +++ b/c/src/api/core/core_api.h @@ -0,0 +1,60 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/blockchainsllc/in3 + * + * Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC + * + * + * COMMERCIAL LICENSE USAGE + * + * Licensees holding a valid commercial license may use this file in accordance + * with the commercial license agreement provided with the Software or, alternatively, + * in accordance with the terms contained in a written agreement between you and + * slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further + * information please contact slock.it at in3@slock.it. + * + * Alternatively, this file may be used under the AGPL license as follows: + * + * AGPL LICENSE USAGE + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Affero General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + * [Permissions of this strong copyleft license are conditioned on making available + * complete source code of licensed works and modifications, which include larger + * works using a licensed work, under the same license. Copyright and license notices + * must be preserved. Contributors provide an express grant of patent rights.] + * You should have received a copy of the GNU Affero General Public License along + * with this program. If not, see . + *******************************************************************************/ + +// @PUBLIC_HEADER +/** @file + * Ethereum API. + * + * This header-file defines easy to use function, which are preparing the JSON-RPC-Request, which is then executed and verified by the incubed-client. + * */ + +#ifndef CORE_API_H +#define CORE_API_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "../../core/client/client.h" +#include "../utils/api_utils.h" + +/** + * register core-api + */ +in3_ret_t in3_register_core_api(in3_t* c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/api/core/rpc.yml b/c/src/api/core/rpc.yml new file mode 100644 index 000000000..ee2a218db --- /dev/null +++ b/c/src/api/core/rpc.yml @@ -0,0 +1,74 @@ +utils: + in3_cacheClear: + sync: true + descr: clears the incubed cache (usually found in the .in3-folder) + result: + descr: true indicating the success + example: + request: [] + response: true + + web3_clientVersion: + descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. + result: + descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. + + keccak: + sync: true + alias: web3_sha3 + + web3_sha3: + sync: true + descr: | + Returns Keccak-256 (not the standardized SHA3-256) of the given data. + + See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + result: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" + + sha256: + sync: true + descr: | + Returns sha-256 of the given data. + + No proof needed, since the client will execute this locally. + params: + data: + descr: data to hash + type: bytes + result: + descr: the 32byte hash of the data + example: + request: + - "0x1234567890" + response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" + + +account: + + in3_createKey: + sync: true + descr: | + Generates 32 random bytes. + If /dev/urandom is available it will be used and should generate a secure random number. + If not the number should not be considered sceure or used in production. + params: + seed: + optional: true + descr: the seed. If given the result will be deterministic. + type: bytes + result: + descr: the 32byte random data + example: + request: [] + response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index fda733b68..407a5827a 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -116,60 +116,6 @@ utils: - 3 response: "0.158" - in3_cacheClear: - sync: true - descr: clears the incubed cache (usually found in the .in3-folder) - result: - descr: true indicating the success - example: - request: [] - response: true - - web3_clientVersion: - descr: Returns the underlying client version. See [web3_clientversion](https://eth.wiki/json-rpc/API#web3_clientversion) for spec. - result: - descr: when connected to the incubed-network, `Incubed/` will be returned, but in case of a direct enpoint, its's version will be used. - - keccak: - sync: true - alias: web3_sha3 - - web3_sha3: - sync: true - descr: | - Returns Keccak-256 (not the standardized SHA3-256) of the given data. - - See [web3_sha3](https://eth.wiki/json-rpc/API#web3_sha3) for spec. - - No proof needed, since the client will execute this locally. - params: - data: - descr: data to hash - type: bytes - result: - descr: the 32byte hash of the data - example: - request: - - "0x1234567890" - response: "0x3a56b02b60d4990074262f496ac34733f870e1b7815719b46ce155beac5e1a41" - - sha256: - sync: true - descr: | - Returns sha-256 of the given data. - - No proof needed, since the client will execute this locally. - params: - data: - descr: data to hash - type: bytes - result: - descr: the 32byte hash of the data - example: - request: - - "0x1234567890" - response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - in3_calcDeployAddress: descr: calculates the address of a contract about to deploy. The address depends on the senders nonce. params: @@ -382,24 +328,6 @@ account: - test response: "0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546" - - in3_createKey: - sync: true - descr: | - Generates 32 random bytes. - If /dev/urandom is available it will be used and should generate a secure random number. - If not the number should not be considered sceure or used in production. - params: - seed: - optional: true - descr: the seed. If given the result will be deterministic. - type: bytes - result: - descr: the 32byte random data - example: - request: [] - response: "0x6c450e037e79b76f231a71a22ff40403f7d9b74b15e014e52fe1156d3666c3e6" - eth_sign: descr: | The sign method calculates an Ethereum specific signature with: diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index b55924676..7655a2382 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -143,29 +143,6 @@ static in3_ret_t in3_ens(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_with_bytes(ctx, bytes(result, res_len)); } -static in3_ret_t in3_sha3(in3_rpc_handle_ctx_t* ctx) { - if (!ctx->params || d_len(ctx->params) != 1) return req_set_error(ctx->req, "no data", IN3_EINVAL); - bytes32_t hash; - keccak(d_to_bytes(ctx->params + 1), hash); - return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); -} -static in3_ret_t in3_sha256(in3_rpc_handle_ctx_t* ctx) { - if (!ctx->params || d_len(ctx->params) != 1) return req_set_error(ctx->req, "no data", IN3_EINVAL); - bytes32_t hash; - bytes_t data = d_to_bytes(ctx->params + 1); - SHA256_CTX c; - sha256_Init(&c); - sha256_Update(&c, data.data, data.len); - sha256_Final(&c, hash); - return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); -} -static in3_ret_t web3_clientVersion(in3_rpc_handle_ctx_t* ctx) { - // for local chains, we return the client version of rpc endpoint. - return ctx->req->client->chain.chain_id == CHAIN_ID_LOCAL - ? IN3_EIGNORE - : in3_rpc_handle_with_string(ctx, "\"Incubed/" IN3_VERSION "\""); -} - static const char* UNITS[] = { "wei", "", "kwei", "\x03", @@ -350,33 +327,6 @@ static in3_ret_t in3_fromWei(in3_rpc_handle_ctx_t* ctx) { return r; } -static in3_ret_t in3_config(in3_rpc_handle_ctx_t* ctx) { - if (!ctx->params || d_len(ctx->params) != 1 || d_type(ctx->params + 1) != T_OBJECT) return req_set_error(ctx->req, "no valid config-object as argument", IN3_EINVAL); - - ctx->req->client->pending--; // we need to to temporarly decrees it in order to allow configuring - str_range_t r = d_to_json(ctx->params + 1); - char old = r.data[r.len]; - r.data[r.len] = 0; - char* ret = in3_configure(ctx->req->client, r.data); - r.data[r.len] = old; - ctx->req->client->pending++; - - if (ret) { - req_set_error(ctx->req, ret, IN3_ECONFIG); - free(ret); - return IN3_ECONFIG; - } - - return in3_rpc_handle_with_string(ctx, "true"); -} - -static in3_ret_t in3_getConfig(in3_rpc_handle_ctx_t* ctx) { - char* ret = in3_get_config(ctx->req->client); - in3_rpc_handle_with_string(ctx, ret); - _free(ret); - return IN3_OK; -} - static in3_ret_t in3_pk2address(in3_rpc_handle_ctx_t* ctx) { bytes_t* pk = d_get_bytes_at(ctx->params, 0); if (!pk || pk->len != 32 || d_len(ctx->params) != 1) return req_set_error(ctx->req, "Invalid private key! must be 32 bytes long", IN3_EINVAL); @@ -541,10 +491,6 @@ static in3_ret_t in3_sign_data(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_finish(ctx); } -static in3_ret_t in3_cacheClear(in3_rpc_handle_ctx_t* ctx) { - TRY(in3_plugin_execute_first(ctx->req, PLGN_ACT_CACHE_CLEAR, NULL)); - return in3_rpc_handle_with_string(ctx, "true"); -} static in3_ret_t in3_decryptKey(in3_rpc_handle_ctx_t* ctx) { d_token_t* keyfile = d_get_at(ctx->params, 0); @@ -587,39 +533,6 @@ static in3_ret_t in3_prepareTx(in3_rpc_handle_ctx_t* ctx) { return IN3_OK; } -static in3_ret_t in3_createKey(in3_rpc_handle_ctx_t* ctx) { - bytes32_t hash; - FILE* r = NULL; - if (d_len(ctx->params) == 1) { - CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) - keccak(d_to_bytes(ctx->params + 1), hash); - srand(bytes_to_int(hash, 4)); - } - else { -#ifndef WASM - r = fopen("/dev/urandom", "r"); - if (r) { - for (int i = 0; i < 32; i++) hash[i] = (uint8_t) fgetc(r); - fclose(r); - } - else -#endif - srand(current_ms() % 0xFFFFFFFF); - } - - if (!r) { -#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) - unsigned int number; - for (int i = 0; i < 32; i++) { - hash[i] = (rand_s(&number) ? rand() : (int) number) % 256; - } -#else - for (int i = 0; i < 32; i++) hash[i] = rand() % 256; -#endif - } - return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); -} - static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) d_token_t* tx_data = ctx->params + 1; @@ -660,10 +573,6 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi UNUSED_VAR(action); in3_rpc_handle_ctx_t* ctx = plugin_ctx; - TRY_RPC("web3_sha3", in3_sha3(ctx)) - TRY_RPC("keccak", in3_sha3(ctx)) - TRY_RPC("sha256", in3_sha256(ctx)) - TRY_RPC("web3_clientVersion", web3_clientVersion(ctx)) TRY_RPC("eth_sign", in3_sign_data(ctx)) TRY_RPC("eth_signTransaction", in3_signTx(ctx)) @@ -675,17 +584,13 @@ static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugi TRY_RPC("in3_ens", in3_ens(ctx)) TRY_RPC("in3_toWei", in3_toWei(ctx)) TRY_RPC("in3_fromWei", in3_fromWei(ctx)) - TRY_RPC("in3_config", in3_config(ctx)) - TRY_RPC("in3_getConfig", in3_getConfig(ctx)) TRY_RPC("in3_pk2address", in3_pk2address(ctx)) TRY_RPC("in3_pk2public", in3_pk2address(ctx)) TRY_RPC("in3_ecrecover", in3_ecrecover(ctx)) TRY_RPC("in3_signData", in3_sign_data(ctx)) - TRY_RPC("in3_cacheClear", in3_cacheClear(ctx)) TRY_RPC("in3_decryptKey", in3_decryptKey(ctx)) TRY_RPC("in3_prepareTx", in3_prepareTx(ctx)) TRY_RPC("in3_signTx", in3_signTx(ctx)) - TRY_RPC("in3_createKey", in3_createKey(ctx)) TRY_RPC("in3_calcDeployAddress", in3_calcDeployAddress(ctx)) return IN3_EIGNORE; From 9cb5a145880b4c2e8b89fa8694c9e784c4f808f0 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 11 May 2021 12:14:05 +0200 Subject: [PATCH 170/221] format --- c/src/api/core/core_api.c | 2 -- c/src/api/eth1/rpc_api.c | 1 - 2 files changed, 3 deletions(-) diff --git a/c/src/api/core/core_api.c b/c/src/api/core/core_api.c index 03af231eb..55111d0a7 100644 --- a/c/src/api/core/core_api.c +++ b/c/src/api/core/core_api.c @@ -47,7 +47,6 @@ #include #include - static in3_ret_t in3_sha3(in3_rpc_handle_ctx_t* ctx) { if (!ctx->params || d_len(ctx->params) != 1) return req_set_error(ctx->req, "no data", IN3_EINVAL); bytes32_t hash; @@ -136,7 +135,6 @@ static in3_ret_t in3_createKey(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_with_bytes(ctx, bytes(hash, 32)); } - static in3_ret_t handle_intern(void* pdata, in3_plugin_act_t action, void* plugin_ctx) { UNUSED_VAR(pdata); UNUSED_VAR(action); diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index 7655a2382..a8267fcaf 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -491,7 +491,6 @@ static in3_ret_t in3_sign_data(in3_rpc_handle_ctx_t* ctx) { return in3_rpc_handle_finish(ctx); } - static in3_ret_t in3_decryptKey(in3_rpc_handle_ctx_t* ctx) { d_token_t* keyfile = d_get_at(ctx->params, 0); bytes_t password_bytes = d_to_bytes(d_get_at(ctx->params, 1)); From 744c31f047c77c293916814572d323a7e3e9ee17 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 11 May 2021 12:50:23 +0200 Subject: [PATCH 171/221] only check for jni-headers --- java/src/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/src/CMakeLists.txt b/java/src/CMakeLists.txt index a9e777b5f..78bbca1d1 100644 --- a/java/src/CMakeLists.txt +++ b/java/src/CMakeLists.txt @@ -38,6 +38,11 @@ target_link_libraries(in3_jni init) IF (NOT DEFINED ANDROID_ABI) + set(JAVA_AWT_LIBRARY NotNeeded) + set(JAVA_JVM_LIBRARY NotNeeded) + set(JAVA_INCLUDE_PATH2 NotNeeded) + set(JAVA_AWT_INCLUDE_PATH NotNeeded) + find_package(Java REQUIRED) find_package(JNI REQUIRED) include(UseJava) From 78f88b95d56755b759569a1210dc37d567124fa2 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 11 May 2021 13:07:42 +0200 Subject: [PATCH 172/221] fix core_api plugin --- c/options.cmake | 5 +++++ c/src/api/core/CMakeLists.txt | 3 ++- c/test/runner.c | 2 ++ c/test/unit_tests/test_config.c | 2 ++ c/test/unit_tests/test_request.c | 2 ++ c/test/unit_tests/test_rpc_api.c | 2 ++ 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/c/options.cmake b/c/options.cmake index ddd2f4adf..58fc2cc1b 100644 --- a/c/options.cmake +++ b/c/options.cmake @@ -49,6 +49,7 @@ OPTION(NODESELECT_DEF_WL "Enable default nodeselect whitelist implementation" ON OPTION(PLGN_CLIENT_DATA "Enable client-data plugin" OFF) OPTION(THREADSAFE "uses mutex to protect shared nodelist access" ON) OPTION(SWIFT "swift API for swift bindings" OFF) +OPTION(CORE_API "include basic core-utils" ON) IF (DEFINED ANDROID_ABI) @@ -82,6 +83,10 @@ IF (PK_SIGNER) set(IN3_API ${IN3_API} pk_signer) ENDIF (PK_SIGNER) +IF (CORE_API) + set(IN3_API ${IN3_API} core_api) +ENDIF (CORE_API) + if (USE_PRECOMPUTED_EC) ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=1) else() diff --git a/c/src/api/core/CMakeLists.txt b/c/src/api/core/CMakeLists.txt index 0fe7eb44a..8a969b3fe 100644 --- a/c/src/api/core/CMakeLists.txt +++ b/c/src/api/core/CMakeLists.txt @@ -36,7 +36,8 @@ add_static_library( NAME core_api REGISTER in3_register_core_api - OPTION "registers a chain independend rpc-methods util-functions" + OPTION CORE_API + DESCR "registers a chain independend rpc-methods util-functions" SOURCES core_api.c diff --git a/c/test/runner.c b/c/test/runner.c index ab0dfacda..e1abedd7a 100644 --- a/c/test/runner.c +++ b/c/test/runner.c @@ -35,6 +35,7 @@ #ifndef TEST #define TEST #endif +#include "../src/api/core/core_api.h" #include "../src/api/eth1/eth_api.h" #include "../src/core/client/client.h" #include "../src/core/client/plugin.h" @@ -458,6 +459,7 @@ int main(int argc, char* argv[]) { in3_register_default(in3_register_eth_api); in3_register_default(in3_register_ipfs); in3_register_default(in3_register_btc); + in3_register_default(in3_register_core_api); in3_register_default(in3_register_nodeselect_def); int i = 0, size = 1; diff --git a/c/test/unit_tests/test_config.c b/c/test/unit_tests/test_config.c index c87b72a9e..2822946a2 100644 --- a/c/test/unit_tests/test_config.c +++ b/c/test/unit_tests/test_config.c @@ -40,6 +40,7 @@ #endif #include "../../src/api/eth1/eth_api.h" +#include "../../src/api/core/core_api.h" #include "../../src/core/client/plugin.h" #include "../../src/core/util/data.h" #include "../../src/core/util/debug.h" @@ -54,6 +55,7 @@ void test_get_config() { in3_register_default(in3_register_eth_nano); + in3_register_default(in3_register_core_api); in3_register_default(in3_register_eth_api); in3_register_default(in3_register_nodeselect_def); in3_t* c = in3_for_chain(0); diff --git a/c/test/unit_tests/test_request.c b/c/test/unit_tests/test_request.c index 704cbebfb..80ee42d2e 100644 --- a/c/test/unit_tests/test_request.c +++ b/c/test/unit_tests/test_request.c @@ -39,6 +39,7 @@ #define DEBUG #endif +#include "../../src/api/core/core_api.h" #include "../../src/api/eth1/eth_api.h" #include "../../src/core/client/keys.h" #include "../../src/core/client/request_internal.h" @@ -922,6 +923,7 @@ int main() { // in3_log_set_level(LOG_TRACE); in3_register_default(in3_register_eth_basic); in3_register_default(in3_register_eth_api); + in3_register_default(in3_register_core_api); in3_register_default(in3_register_nodeselect_def); TESTS_BEGIN(); diff --git a/c/test/unit_tests/test_rpc_api.c b/c/test/unit_tests/test_rpc_api.c index d9feb0372..94e1afe5b 100644 --- a/c/test/unit_tests/test_rpc_api.c +++ b/c/test/unit_tests/test_rpc_api.c @@ -39,6 +39,7 @@ #define DEBUG #endif #include "../../src/api/eth1/abi.h" +#include "../../src/api/core/core_api.h" #include "../../src/api/eth1/eth_api.h" #include "../../src/core/client/keys.h" #include "../../src/core/client/request_internal.h" @@ -318,6 +319,7 @@ static void test_in3_verified_hashes() { int main() { in3_register_default(in3_register_eth_full); in3_register_default(in3_register_eth_api); + in3_register_default(in3_register_core_api); in3_register_default(in3_register_nodeselect_def); in3_log_set_quiet(true); From 97b756277ba7ccccc3ca2ee6e15bde7bb83c1720 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 11 May 2021 13:12:57 +0200 Subject: [PATCH 173/221] fix java --- java/src/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/java/src/CMakeLists.txt b/java/src/CMakeLists.txt index 78bbca1d1..cd4579b55 100644 --- a/java/src/CMakeLists.txt +++ b/java/src/CMakeLists.txt @@ -40,7 +40,6 @@ IF (NOT DEFINED ANDROID_ABI) set(JAVA_AWT_LIBRARY NotNeeded) set(JAVA_JVM_LIBRARY NotNeeded) - set(JAVA_INCLUDE_PATH2 NotNeeded) set(JAVA_AWT_INCLUDE_PATH NotNeeded) find_package(Java REQUIRED) From 4d0f2f7421a57adb76bceb428802b9a7b01e250b Mon Sep 17 00:00:00 2001 From: jbentke Date: Wed, 12 May 2021 13:54:02 +0200 Subject: [PATCH 174/221] fixed getBlockByHash second parameter --- c/src/verifier/eth1/basic/rpc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index 9086a42b3..f10e78442 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -319,7 +319,7 @@ eth: result: type: blockdataWithTxHashes - params: - fullTx: false + fullTx: true name: getBlockByHashWithTx descr: returns the given Block by hash with full transaction data result: @@ -1122,4 +1122,4 @@ eth: type: bytes32 - \ No newline at end of file + From 72ed580f7670ab41044e58ecdb7288558e06a8d7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 13 May 2021 14:58:04 +0200 Subject: [PATCH 175/221] fix count --- c/src/verifier/eth1/basic/rpc.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index f10e78442..ae189ff23 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -385,6 +385,7 @@ eth: alias: eth_getUncleCountByBlockNumber result: descr: the number of transactions in the block + type: int eth_getBlockTransactionCountByNumber: descr: returns the number of transactions. For Spec, see [eth_getBlockTransactionCountByNumber](https://eth.wiki/json-rpc/API#eth_getBlockTransactionCountByNumber). @@ -396,6 +397,7 @@ eth: alias: eth_getUncleCountByBlockNumber result: descr: the number of transactions in the block + type: int eth_getUncleCountByBlockHash: descr: returns the number of uncles. For Spec, see [eth_getUncleCountByBlockHash](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockHash). @@ -407,6 +409,7 @@ eth: alias: eth_getUncleCountByBlockNumber result: descr: the number of uncles + type: int eth_getUncleCountByBlockNumber: descr: returns the number of uncles. For Spec, see [eth_getUncleCountByBlockNumber](https://eth.wiki/json-rpc/API#eth_getUncleCountByBlockNumber). @@ -426,6 +429,7 @@ eth: - `uncles`: a array of blockheaders of the uncles of the block. This is only needed if the number of uncles are requested. result: descr: the number of uncles + type: int eth_getTransactionByBlockHashAndIndex: descr: | @@ -807,6 +811,7 @@ eth: type: uint64 result: descr: the nonce + type: uint64 proof: alias: eth_getStorageAt example: From 121771498f2b1038c69c4c6fad49780183117f8b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 13 May 2021 17:26:31 +0200 Subject: [PATCH 176/221] added debug --- c/src/core/client/rpc.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/c/src/core/client/rpc.yml b/c/src/core/client/rpc.yml index badd47e89..cb7088e42 100644 --- a/c/src/core/client/rpc.yml +++ b/c/src/core/client/rpc.yml @@ -38,6 +38,13 @@ config: optional: true default: false + debug: + type: bool + descr: if true, debug messages will be written to stderr. + example: true + optional: true + default: false + maxAttempts: type: int descr: max number of attempts in case a response is rejected. From 9b30f4cc1c9c604cebeefb6175850cd4ee666a79 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 17 May 2021 13:39:07 +0200 Subject: [PATCH 177/221] fixed difficulty --- c/src/verifier/btc/rpc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index ffb961650..1578b4d74 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -175,7 +175,7 @@ types: type: bytes4 difficulty: descr: The difficulty - type: uint256 + type: double chainwork: descr: Expected number of hashes required to produce the current chain (in hex) type: hex @@ -226,7 +226,7 @@ types: type: bytes4 difficulty: descr: The difficulty - type: uint256 + type: double chainwork: descr: Expected number of hashes required to produce the current chain (in hex) type: hex From 75e95225554d6c4f5d9f40794c6e2f2676578c76 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 18 May 2021 08:56:00 +0200 Subject: [PATCH 178/221] fix asmjs-config issue --- wasm/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm/src/CMakeLists.txt b/wasm/src/CMakeLists.txt index a140ad36d..b849dca0b 100644 --- a/wasm/src/CMakeLists.txt +++ b/wasm/src/CMakeLists.txt @@ -37,7 +37,7 @@ set(EMC_PROPS "-s ALLOW_MEMORY_GROWTH=1 -s NODEJS_CATCH_REJECTION=0 -s EXPORT_NA IF (ASMJS) set(WASM_EMBED true) set(CMAKE_EXECUTABLE_SUFFIX ".js") - set(EMC_PROPS "${EMC_PROPS} -s FINALIZE_ASM_JS=1 -s SEPARATE_ASM=1 -s WASM=0 -s ASM_JS=1 ") + set(EMC_PROPS "${EMC_PROPS} -s FINALIZE_ASM_JS=1 -s WASM=0 -s ASM_JS=1 ") else(ASMJS) set(EMC_PROPS "${EMC_PROPS} -s WASM=1") endif(ASMJS) From 244e210cee6e0b8d38294cc40ba43527edb8eeb5 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 18 May 2021 08:56:22 +0200 Subject: [PATCH 179/221] set a finality for btc if not configured --- c/src/core/client/client_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c index 2a80fa699..d844df797 100644 --- a/c/src/core/client/client_init.c +++ b/c/src/core/client/client_init.c @@ -265,6 +265,7 @@ char* in3_configure(in3_t* c, const char* config) { bool changed = (c->chain.chain_id != chain_id(token)); c->chain.chain_id = chain_id(token); c->chain.type = ct_ == -1 ? chain_type_from_id(c->chain.chain_id) : ((in3_chain_type_t) ct_); + if (c->chain.chain_id == CHAIN_ID_BTC && !c->finality && !d_get(json->result,key("finality"))) c->finality = 7; in3_client_register_chain(c, c->chain.chain_id, c->chain.type, 2); if (changed) in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); } From 2df5ef40ba34dce6e08bb75ab85d2280de1aa2e7 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 18 May 2021 08:56:53 +0200 Subject: [PATCH 180/221] make sure we don't clean up with a null cptr --- c/src/core/client/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c index a5afc80b2..39eac1b6f 100644 --- a/c/src/core/client/execute.c +++ b/c/src/core/client/execute.c @@ -683,7 +683,7 @@ typedef struct { static void transport_cleanup(in3_req_t* ctx, ctx_req_transports_t* transports, bool free_all) { for (int i = 0; i < transports->len; i++) { - if (free_all || transports->req[i].req == ctx) { + if ((free_all && transports->req[i].req) || transports->req[i].req == ctx) { in3_http_request_t req = {.req = ctx, .cptr = transports->req[i].ptr, .urls_len = 0, .urls = NULL, .payload = NULL}; in3_plugin_execute_first_or_none(ctx, PLGN_ACT_TRANSPORT_CLEAN, &req); if (!free_all) { From 4c4ff007d8de6bafab54f5438f3b78d47698e46d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 18 May 2021 09:36:10 +0200 Subject: [PATCH 181/221] format --- c/src/core/client/client_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c index d844df797..bb91a883e 100644 --- a/c/src/core/client/client_init.c +++ b/c/src/core/client/client_init.c @@ -265,7 +265,7 @@ char* in3_configure(in3_t* c, const char* config) { bool changed = (c->chain.chain_id != chain_id(token)); c->chain.chain_id = chain_id(token); c->chain.type = ct_ == -1 ? chain_type_from_id(c->chain.chain_id) : ((in3_chain_type_t) ct_); - if (c->chain.chain_id == CHAIN_ID_BTC && !c->finality && !d_get(json->result,key("finality"))) c->finality = 7; + if (c->chain.chain_id == CHAIN_ID_BTC && !c->finality && !d_get(json->result, key("finality"))) c->finality = 7; in3_client_register_chain(c, c->chain.chain_id, c->chain.type, 2); if (changed) in3_plugin_execute_all(c, PLGN_ACT_CHAIN_CHANGE, c); } From edfcc93615ed358eba0bc4534808fc0f75b097a6 Mon Sep 17 00:00:00 2001 From: chirag-parmar Date: Tue, 25 May 2021 14:51:23 +0200 Subject: [PATCH 182/221] rpc.yml fix for btc getBlockHeaderAsHex --- c/src/verifier/btc/rpc.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index 1578b4d74..f97f894de 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -293,8 +293,8 @@ btc: type: bytes32 verbosity: descr: 0 or false for the hex-encoded data, 1 or true for a json object - type: int - default: 0 + type: bool + default: false in3Params: verification: descr: defines the kind of proof the client is asking for (must be `never` or `proof`) @@ -305,7 +305,7 @@ btc: result: options: - params: - verbosity: 0 + verbosity: false name: getblockheaderAsHex descr: returns a hex representation of the blockheader example: '3045022100ae5bd019a63aed404b743c9ebcc77fbaa657e481f745e4...f3255d' @@ -313,7 +313,7 @@ btc: optional: true type: bytes - params: - verbosity: 1 + verbosity: true name: getblockheader descr: returns the blockheader result: From 67fc63bcd34b77a77cffb7efd1238ec72f153530 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 25 May 2021 18:55:08 +0200 Subject: [PATCH 183/221] fix net_version --- c/src/api/eth1/rpc.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/c/src/api/eth1/rpc.yml b/c/src/api/eth1/rpc.yml index 407a5827a..0919200a6 100644 --- a/c/src/api/eth1/rpc.yml +++ b/c/src/api/eth1/rpc.yml @@ -109,6 +109,7 @@ utils: optional: true result: descr: the value as string. + type: string example: request: - "0x234324abadefdef" @@ -137,10 +138,11 @@ utils: net_version: - sync: true - descr: the Network Version (currently 1) + descr: Returns the current network id. + apiName: getNetworkId result: - descr: the Version number + descr: the network id + type: uint64 account: descr: | From a5b32ee1b7aba1808b56aaaf00f6344ec209d1c4 Mon Sep 17 00:00:00 2001 From: jbentke Date: Wed, 26 May 2021 15:31:34 +0200 Subject: [PATCH 184/221] made nonce optional for goerli support --- c/src/verifier/eth1/basic/rpc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index ae189ff23..ea006fdde 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -45,6 +45,7 @@ types: nonce: descr: hash of the generated proof-of-work. `null` when its pending block. type: uint256 + optional: true sha3Uncles: descr: SHA3 of the uncles Merkle root in the block. type: bytes32 From 6b033b9b93510b45828efa24bb6d8c53147d6751 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 26 May 2021 16:27:58 +0200 Subject: [PATCH 185/221] fixed zksync api --- c/src/pay/zksync/rpc.yml | 105 +++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 98f2fadd1..1d8f38737 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -1,3 +1,34 @@ +types: + zk_receipt: + type: + descr: the Transaction-Type (`Withdraw` or `Transfer`) + type: string + accountId: + descr: the id of the sender account + type: uint64 + from: + descr: the address of the sender + type: address + to: + descr: the address of the receipient + type: address + token: + descr: the id of the token used + type: uint64 + amount: + descr: the amount sent + type: uint256 + fee: + descr: the fees paid + type: uint256 + nonce: + descr: the fees paid + type: uint64 + txHash: + descr: the transactionHash, which can be used to track the tx + type: string + + zksync: descr: | *Important: This feature is still experimental and not considered stable yet. In order to use it, you need to set the experimental-flag (-x on the comandline or `"experimental":true`!* @@ -246,6 +277,7 @@ zksync: block: descr: the blockNumber containing the tx or `null` if still pending type: uint64 + optional: true executed: descr: true, if the tx has been executed by the operator. If false it is still in the txpool of the operator. type: bool @@ -255,6 +287,7 @@ zksync: failReason: descr: if executed and failed this will include an error message type: string + optional: true example: cmdParams: -x request: @@ -483,14 +516,48 @@ zksync: type: address optional: true result: - descr: the opId. You can use `zksync_ethop_info` to follow the state-changes. - type: uint64 + descr: the receipt and the receipopId. You can use `zksync_ethop_info` to follow the state-changes. + type: + receipt: + descr: the transactionreceipt + type: transactionReceipt + priorityOpId: + descr: the operationId to rack to progress + type: uint64 + example: cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c request: - 1000 - WBTC - response: 74 + response: + receipt: + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + contractAddress: + cumulativeGasUsed: '0x2466d' + gasUsed: '0x2466d' + logs: + - address: '0x85ec283a3ed4b66df4da23656d4bf8a507383bca' + blockHash: '0xea6ee1e20d3408ad7f6981cfcc2625d80b4f4735a75ca5b20baeb328e41f0304' + blockNumber: '0x8c1e39' + data: 0x00000000000... + logIndex: '0x0' + removed: false + topics: + - '0x9123e6a7c5d144bd06140643c88de8e01adcbb24350190c02218a4435c7041f8' + - '0xa2f7689fc12ea917d9029117d32b9fdef2a53462c853462ca86b71b97dd84af6' + - '0x55a6ef49ec5dcf6cd006d21f151f390692eedd839c813a150000000000000000' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + transactionLogIndex: '0x0' + type: mined + logsBloom: 0x00000000000000000000200000... + root: + status: '0x1' + transactionHash: '0x5dc2a9ec73abfe0640f27975126bbaf14624967e2b0b7c2b3a0fb6111f0d3c5e' + transactionIndex: '0x0' + priorityOpId: 74 zksync_transfer: descr: sends a zksync-transaction and returns data including the transactionHash. @@ -509,15 +576,25 @@ zksync: type: address optional: true result: - descr: the transactionHash. use `zksync_tx_info` to check the progress. - type: bytes32 + descr: the transactionReceipt. use `zksync_tx_info` to check the progress. + type: zk_receipt example: cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c request: - 0xabea9132b05a70803a4e85094fd0e1800777fbef - 100 - WBTC - response: '0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1' + response: + type: Transfer + accountId: 1 + from: '0x8a91dc2d28b689474298d91899f0c1baf62cb85b' + to: '0x8a91dc2d28b689474298d91899f0c1baf62cb85b' + token: 0 + amount: 10 + fee: 3780000000000000 + nonce: 4 + txHash: 'sync-tx:40008d91ab92f7c539e45b06e708e186a4b906ad10c4b7a29f855fe02e7e7668' + zksync_withdraw: descr: withdraws the amount to the given `ethAddress` for the given token. @@ -536,15 +613,25 @@ zksync: type: address optional: true result: - descr: the transactionHash. use `zksync_tx_info` to check the progress. - type: bytes32 + descr: the transactionReceipt. use `zksync_tx_info` to check the progress. + type: zk_receipt example: cmdParams: -x -pk 0xb0f60e4783ccc1f6234deed9e21f16d460c4176fd7adbd4f31d17e283b8cfb1c request: - 0xabea9132b05a70803a4e85094fd0e1800777fbef - 100 - WBTC - response: '0x58ba1537596739d990a33e4fba3a6fb4e0d612c5de30843a2c415dd1e5edcef1' + response: + type: Transfer + accountId: 1 + from: '0x8a91dc2d28b689474298d91899f0c1baf62cb85b' + to: '0x8a91dc2d28b689474298d91899f0c1baf62cb85b' + token: 0 + amount: 10 + fee: 3780000000000000 + nonce: 4 + txHash: 'sync-tx:40008d91ab92f7c539e45b06e708e186a4b906ad10c4b7a29f855fe02e7e7668' + zksync_emergency_withdraw: descr: withdraws all tokens for the specified token as a onchain-transaction. This is useful in case the zksync-server is offline or tries to be malicious. From 88557f1f244a512ac017857b58c0e74fa3c5db27 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 28 May 2021 16:35:37 +0200 Subject: [PATCH 186/221] change create2 calculation --- c/src/pay/zksync/zk_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/pay/zksync/zk_helper.c b/c/src/pay/zksync/zk_helper.c index 8a238984a..8f6d45f7a 100644 --- a/c/src/pay/zksync/zk_helper.c +++ b/c/src/pay/zksync/zk_helper.c @@ -86,8 +86,8 @@ void zksync_calculate_account(address_t creator, bytes32_t codehash, bytes32_t s uint8_t tmp[85]; memset(tmp, 0, 85); memcpy(tmp, saltarg, 32); - memcpy(tmp + 32 + 12, pub_key_hash, 20); - keccak(bytes(tmp, 64), tmp + 21); + memcpy(tmp + 32 , pub_key_hash, 20); + keccak(bytes(tmp, 52), tmp + 21); *tmp = 0xff; memcpy(tmp + 1, creator, 20); memcpy(tmp + 53, codehash, 32); From 25a3310b8701865ee4b3be82f8957f480061750b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 28 May 2021 17:46:17 +0200 Subject: [PATCH 187/221] format --- c/src/pay/zksync/zk_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/pay/zksync/zk_helper.c b/c/src/pay/zksync/zk_helper.c index 8f6d45f7a..ba401213e 100644 --- a/c/src/pay/zksync/zk_helper.c +++ b/c/src/pay/zksync/zk_helper.c @@ -86,7 +86,7 @@ void zksync_calculate_account(address_t creator, bytes32_t codehash, bytes32_t s uint8_t tmp[85]; memset(tmp, 0, 85); memcpy(tmp, saltarg, 32); - memcpy(tmp + 32 , pub_key_hash, 20); + memcpy(tmp + 32, pub_key_hash, 20); keccak(bytes(tmp, 52), tmp + 21); *tmp = 0xff; memcpy(tmp + 1, creator, 20); From 363150f7da9f0a35a41fa0dd62f818f1a5457c11 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 08:05:43 +0200 Subject: [PATCH 188/221] add valid in zksync --- c/src/pay/zksync/zk_message.c | 65 +++++++++++++++++++++-------------- c/src/pay/zksync/zk_setkey.c | 16 ++++++--- c/src/pay/zksync/zksync.h | 8 ++++- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/c/src/pay/zksync/zk_message.c b/c/src/pay/zksync/zk_message.c index cc6efa11f..136513a62 100644 --- a/c/src/pay/zksync/zk_message.c +++ b/c/src/pay/zksync/zk_message.c @@ -149,7 +149,7 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy raw[45] = (tid >> 8) & 0xff; // 45: token_id (2) raw[46] = tid & 0xff; // if (data->type == ZK_WITHDRAW) { - total = 69; + total = 85; #ifdef ZKSYNC_256 memcpy(raw + 47, data->amount + 16, 16); #else @@ -161,7 +161,7 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy int_to_bytes(data->nonce, raw + 65); // 65: nonce(4) } else { - total = 58; + total = 74; to_dec(dec, data->amount); // create a decimal represntation and pack it TRY(pack(dec, 35, 5, raw + 47, ctx)) // 47: amount packed (5) to_dec(dec, data->fee); // create a decimal represntation and pack it @@ -169,28 +169,29 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy int_to_bytes(data->nonce, raw + 54); // 54: nonce(4) } + long_to_bytes(data->valid.from,raw+total-16); + long_to_bytes(data->valid.to,raw+total-8); + // sign data return zksync_sign(conf, bytes(raw, total), ctx, sig); } in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf) { - char msg_data[200]; + if (!data->valid.to) data->valid.to=0xffffffffl; + char msg_data[216]; bytes_t signature; sb_t msg = sb_stack(msg_data); create_human_readable_tx_info(&msg, data, data->type == ZK_WITHDRAW ? "Withdraw " : "Transfer "); create_signed_bytes(&msg); - if (data->conf->sign_type == ZK_SIGN_CREATE2) { - signature = bytes(alloca(65), 65); - memset(signature.data, 0, 65); - } - else + if (data->conf->sign_type != ZK_SIGN_CREATE2) { TRY(req_require_signature(ctx, SIGN_EC_HASH, &signature, bytes((uint8_t*) msg_data, msg.len), bytes(data->from, 20))) - in3_log_debug("zksync_sign_transfer human readable :\n%s\n", msg_data); + in3_log_debug("zksync_sign_transfer human readable :\n%s\n", msg_data); - if (signature.len == 65 && signature.data[64] < 27) - signature.data[64] += 27; //because EIP155 chainID = 0 + if (signature.len == 65 && signature.data[64] < 27) + signature.data[64] += 27; //because EIP155 chainID = 0 + } // now create the packed sync transfer - uint8_t raw[69], sig[96]; + uint8_t raw[85], sig[96]; TRY(sign_sync_transfer(data, ctx, conf, raw, sig)); if (in3_log_level_is(LOG_DEBUG) || in3_log_level_is(LOG_TRACE)) { @@ -220,6 +221,10 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, sb_add_chars(sb, ",\"fee\":"); sb_add_int(sb, data->fee); #endif + sb_add_chars(sb, ",\"validFrom\":"); + sb_add_int(sb, (int64_t) data->valid.from); + sb_add_chars(sb, ",\"validUntil\":"); + sb_add_int(sb, (int64_t) data->valid.to); sb_add_chars(sb, ",\"nonce\":"); sb_add_int(sb, data->nonce); sb_add_rawbytes(sb, ",\"signature\":{\"pubKey\":\"", bytes(sig, 32), 0); @@ -235,6 +240,8 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, } in3_ret_t zksync_sign(zksync_config_t* conf, bytes_t msg, in3_req_t* ctx, uint8_t* sig) { + in3_log_debug("signing zksync data: \n"); + b_print(&msg); if (memiszero(conf->sync_key, 32)) return req_set_error(ctx, "no signing key set", IN3_ECONFIG); if (!conf->musig_pub_keys.data) return zkcrypto_sign_musig(conf->sync_key, msg, sig); char* p = alloca(msg.len * 2 + 5); @@ -251,11 +258,11 @@ in3_ret_t zksync_sign(zksync_config_t* conf, bytes_t msg, in3_req_t* ctx, uint8_ return IN3_OK; } -in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token) { +in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token, zksync_valid_t valid) { // create sign_msg for the rollup char dec[80]; - uint8_t sign_msg_bytes[53], sig[96]; + uint8_t sign_msg_bytes[69], sig[96]; sign_msg_bytes[0] = 7; // tx type 7 (1 byte) int_to_bytes(conf->account_id, sign_msg_bytes + 1); // acount_id (4 bytes) memcpy(sign_msg_bytes + 5, conf->account, 20); // account address @@ -265,9 +272,11 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub to_dec(dec, fee); // create a decimal represntation and pack it TRY(pack(dec, 11, 5, sign_msg_bytes + 47, ctx)) // 47: fee packed (2) int_to_bytes(nonce, sign_msg_bytes + 49); // nonce + long_to_bytes(valid.from, sign_msg_bytes + 53); // valid_from + long_to_bytes(valid.to, sign_msg_bytes + 61); // valid_to // now sign it with the new pk - TRY(zksync_sign(conf, bytes(sign_msg_bytes, 53), ctx, sig)) + TRY(zksync_sign(conf, bytes(sign_msg_bytes, 69), ctx, sig)) // create human readable message char msg_data[300]; uint8_t tmp[8]; @@ -282,35 +291,41 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub sb_add_chars(&msg, "\n\nOnly sign this message for a trusted client!"); create_signed_bytes(&msg); - if (conf->sign_type != ZK_SIGN_CONTRACT) + if (conf->sign_type != ZK_SIGN_CREATE2) { TRY(req_require_signature(ctx, SIGN_EC_HASH, &signature, bytes((uint8_t*) msg_data, msg.len), bytes(conf->account, 20))) - - if (signature.len == 65 && signature.data[64] < 27) - signature.data[64] += 27; //because EIP155 chainID = 0 + if (signature.len == 65 && signature.data[64] < 27) + signature.data[64] += 27; //because EIP155 chainID = 0 + } sb_add_chars(sb, "{\"type\":\"ChangePubKey\",\"accountId\":"); sb_add_int(sb, conf->account_id); sb_add_rawbytes(sb, ",\"account\":\"0x", bytes(conf->account, 20), 0); sb_add_rawbytes(sb, "\",\"newPkHash\":\"sync:", bytes(sync_pub_key, 20), 0); - sb_add_chars(sb, "\",\"feeToken\":"); + sb_add_chars(sb, "\",\"feeTokenId\":"); sb_add_int(sb, token->id); - sb_add_chars(sb, ",\"fee\":"); + sb_add_chars(sb, ",\"feeToken\":"); + sb_add_int(sb, token->id); + sb_add_chars(sb, ",\"validFrom\":"); + sb_add_int(sb, (int64_t) valid.from); + sb_add_chars(sb, ",\"validUntil\":"); + sb_add_int(sb, (int64_t) valid.to); + sb_add_chars(sb, ",\"fee\":\""); #ifdef ZKSYNC_256 to_dec(dec, fee); sb_add_chars(sb, dec); #else sb_add_int(sb, fee); #endif - sb_add_chars(sb, ",\"nonce\":"); + sb_add_chars(sb, "\",\"nonce\":"); sb_add_int(sb, nonce); if (conf->version > 0) { - sb_add_chars(sb, ",\"changePubkeyType\":{"); + sb_add_chars(sb, ",\"ethAuthData\":{"); if (conf->sign_type == ZK_SIGN_PK) sb_add_rawbytes(sb, "\"type\":\"EthereumSignature\",\"ethSignature\":\"0x", signature, 0); else if (conf->sign_type == ZK_SIGN_CONTRACT) sb_add_rawbytes(sb, "\"type\":\"OnchainTransaction", signature, 0); else if (conf->sign_type == ZK_SIGN_CREATE2 && conf->create2) { - sb_add_rawbytes(sb, "\"type\":\"Create2Contract\",\"creatorAddress\":\"0x", bytes(conf->create2->creator, 20), 0); + sb_add_rawbytes(sb, "\"type\":\"CREATE2\",\"creatorAddress\":\"0x", bytes(conf->create2->creator, 20), 0); sb_add_rawbytes(sb, "\",\"saltArg\":\"0x", bytes(conf->create2->salt_arg, 32), 0); sb_add_rawbytes(sb, "\",\"codeHash\":\"0x", bytes(conf->create2->codehash, 32), 0); } @@ -323,7 +338,7 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub sb_add_chars(sb, "\"},null,false"); } else { - sb_add_chars(sb, "\"},\"ethSignature\":null},null,false"); + sb_add_chars(sb, "\"}},null,false"); } return IN3_OK; diff --git a/c/src/pay/zksync/zk_setkey.c b/c/src/pay/zksync/zk_setkey.c index 8587cc39b..7b6055ffa 100644 --- a/c/src/pay/zksync/zk_setkey.c +++ b/c/src/pay/zksync/zk_setkey.c @@ -58,10 +58,16 @@ static in3_ret_t auth_pub_key(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx, } in3_ret_t zksync_set_key(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { - address_t pub_hash; - uint32_t nonce; - d_token_t* token = d_len(ctx->params) == 1 ? ctx->params + 1 : NULL; - bytes_t* new_key = d_get_bytes_at(ctx->params, 1); + address_t pub_hash; + zksync_valid_t valid; + uint32_t nonce; + int plen = d_len(ctx->params); + d_token_t* token = plen == 1 ? ctx->params + 1 : NULL; + bytes_t* new_key = d_get_bytes_at(ctx->params, 1); + valid.from = plen > 2 ? d_get_long_at(ctx->params, 2) : 0; + valid.to = plen > 3 ? d_get_long_at(ctx->params, 3) : 0; + if (!valid.to) valid.to = 0xffffffffl; + zksync_token_t* token_data = NULL; if (!token) return req_set_error(ctx->req, "Missing fee token as first token", IN3_EINVAL); zk_fee_t fee; @@ -93,7 +99,7 @@ in3_ret_t zksync_set_key(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { } if (!cached) { sb_t sb = {0}; - in3_ret_t ret = zksync_sign_change_pub_key(&sb, ctx->req, pub_hash, nonce, conf, fee, token_data); + in3_ret_t ret = zksync_sign_change_pub_key(&sb, ctx->req, pub_hash, nonce, conf, fee, token_data, valid); if (ret && sb.data) _free(sb.data); TRY(ret) if (!sb.data) return IN3_EUNKNOWN; diff --git a/c/src/pay/zksync/zksync.h b/c/src/pay/zksync/zksync.h index 7d897bcb5..1bf10f837 100644 --- a/c/src/pay/zksync/zksync.h +++ b/c/src/pay/zksync/zksync.h @@ -128,6 +128,11 @@ typedef struct zksync_config { char* proof_create_method; /**< the rpc-method used to create the proof before creating a signature */ } zksync_config_t; +typedef struct valid { + uint64_t from; + uint64_t to; +} zksync_valid_t; + typedef struct pay_criteria { uint_fast32_t payed_nodes; /**< max number of nodes payed at the same time*/ uint64_t max_price_per_hundred_igas; /**< the max price per 100 gas units to accept a payment offer */ @@ -146,6 +151,7 @@ typedef struct { zk_msg_type_t type; /**< message type */ zk_fee_t amount; /**< amount to send */ zk_fee_t fee; /**< ransaction fees */ + zksync_valid_t valid; /**< validity */ } zksync_tx_data_t; /** registers the zksync-plugin in the client */ @@ -167,7 +173,7 @@ NONULL in3_ret_t zksync_emergency_withdraw(zksync_config_t* conf, in3_rpc_handle NONULL in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* req, zksync_config_t* conf); /** creates message data and signs a change_pub_key-message */ -NONULL in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* req, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token); +NONULL in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* req, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token, zksync_valid_t valid); in3_ret_t zksync_musig_sign(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); zk_musig_session_t* zk_musig_session_free(zk_musig_session_t* s); From 65b6feed3e841a55c1c8cc6b43ba89c02fbb741a Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 10:00:32 +0200 Subject: [PATCH 189/221] fix transfer --- c/src/pay/zksync/zk_message.c | 43 ++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/c/src/pay/zksync/zk_message.c b/c/src/pay/zksync/zk_message.c index 136513a62..42d993d36 100644 --- a/c/src/pay/zksync/zk_message.c +++ b/c/src/pay/zksync/zk_message.c @@ -138,8 +138,7 @@ static void create_signed_bytes(sb_t* sb) { memcpy(sb->data + l - strlen(len_num), len_num, strlen(len_num)); } -static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf, uint8_t* raw, uint8_t* sig) { - uint32_t total; +static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf, uint8_t* raw, uint8_t* sig, uint32_t* total) { char dec[80]; uint16_t tid = data->token ? data->token->id : 0; raw[0] = data->type; // 0: type(1) @@ -149,7 +148,7 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy raw[45] = (tid >> 8) & 0xff; // 45: token_id (2) raw[46] = tid & 0xff; // if (data->type == ZK_WITHDRAW) { - total = 85; + *total = 85; #ifdef ZKSYNC_256 memcpy(raw + 47, data->amount + 16, 16); #else @@ -161,7 +160,7 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy int_to_bytes(data->nonce, raw + 65); // 65: nonce(4) } else { - total = 74; + *total = 74; to_dec(dec, data->amount); // create a decimal represntation and pack it TRY(pack(dec, 35, 5, raw + 47, ctx)) // 47: amount packed (5) to_dec(dec, data->fee); // create a decimal represntation and pack it @@ -169,15 +168,15 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy int_to_bytes(data->nonce, raw + 54); // 54: nonce(4) } - long_to_bytes(data->valid.from,raw+total-16); - long_to_bytes(data->valid.to,raw+total-8); + long_to_bytes(data->valid.from, raw + (*total) - 16); + long_to_bytes(data->valid.to, raw + (*total) - 8); // sign data - return zksync_sign(conf, bytes(raw, total), ctx, sig); + return zksync_sign(conf, bytes(raw, (*total)), ctx, sig); } in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf) { - if (!data->valid.to) data->valid.to=0xffffffffl; + if (!data->valid.to) data->valid.to = 0xffffffffl; char msg_data[216]; bytes_t signature; sb_t msg = sb_stack(msg_data); @@ -191,12 +190,13 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, signature.data[64] += 27; //because EIP155 chainID = 0 } // now create the packed sync transfer - uint8_t raw[85], sig[96]; - TRY(sign_sync_transfer(data, ctx, conf, raw, sig)); + uint8_t raw[85], sig[96]; + uint32_t total = 0; + TRY(sign_sync_transfer(data, ctx, conf, raw, sig, &total)); if (in3_log_level_is(LOG_DEBUG) || in3_log_level_is(LOG_TRACE)) { char* hex = alloca(142); - bytes_to_hex(raw, data->type == ZK_WITHDRAW ? 69 : 58, hex); + bytes_to_hex(raw, total, hex); in3_log_debug("zksync_sign_transfer bin :\n%s\n", hex); } @@ -208,6 +208,8 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, sb_add_rawbytes(sb, "\",\"to\":\"0x", bytes(data->to, 20), 0); sb_add_chars(sb, "\",\"token\":"); sb_add_int(sb, data->token->id); + sb_add_chars(sb, ",\"tokenId\":"); + sb_add_int(sb, data->token->id); sb_add_chars(sb, ",\"amount\":"); #ifdef ZKSYNC_256 char dec[80]; @@ -229,13 +231,18 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, sb_add_int(sb, data->nonce); sb_add_rawbytes(sb, ",\"signature\":{\"pubKey\":\"", bytes(sig, 32), 0); sb_add_rawbytes(sb, "\",\"signature\":\"", bytes(sig + 32, 64), 0); - sb_add_chars(sb, "\"}},{\"type\":\""); - if (data->conf->sign_type == ZK_SIGN_CONTRACT) - sb_add_chars(sb, "EIP1271Signature"); - else - sb_add_chars(sb, "EthereumSignature"); - sb_add_rawbytes(sb, "\",\"signature\":\"0x", signature, 0); - sb_add_chars(sb, "\"}"); + sb_add_chars(sb, "\"}},"); + if (data->conf->sign_type == ZK_SIGN_CREATE2) + sb_add_chars(sb, "null"); + else { + sb_add_chars(sb, "{\"type\":\""); + if (data->conf->sign_type == ZK_SIGN_CONTRACT) + sb_add_chars(sb, "EIP1271Signature"); + else + sb_add_chars(sb, "EthereumSignature"); + sb_add_rawbytes(sb, "\",\"signature\":\"0x", signature, 0); + sb_add_chars(sb, "\"}"); + } return IN3_OK; } From 94a72be98b1a8a6c0f42cca19c9ef72ed8859435 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 11:12:39 +0200 Subject: [PATCH 190/221] fix abiDecode-issue --- wasm/src/in3_util.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index e6a13482c..467aa4034 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -221,11 +221,7 @@ function abiDecode(sig, data) { function convertType(val, t) { const isArray = t.indexOf('[') - if (isArray >= 0) { - t = t.substr(0, isArray) - if (t !== 'string' && t != 'bytes') - return val ? val.map(_ => convertType(_, t)) : [] - } + if (isArray >= 0) return val ? val.map(_ => convertType(_, t.substr(0, isArray))) : [] if (t.startsWith('(')) return convertTypes(splitTypes(t), val) switch (t) { From 7633bbecb7d7cf0ed9ee617fc0c78b3106caf1a0 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 13:59:16 +0200 Subject: [PATCH 191/221] fix zksync-signer for pk/eip1271 --- c/include/in3/plugin.h | 1 + c/include/in3/zksync.h | 8 +- c/src/core/client/plugin.h | 5 +- c/src/core/client/request.c | 2 +- c/src/pay/zksync/zk_helper.c | 13 +++- c/src/pay/zksync/zk_message.c | 74 +++++++------------ .../ledger-nano/signer/ethereum_apdu_client.c | 1 + .../signer/ledger-nano/signer/ledger_signer.c | 1 + c/src/signer/multisig/multisig.c | 14 +++- c/src/signer/pk-signer/signer.c | 13 ++++ wasm/src/wasm.c | 12 +++ 11 files changed, 86 insertions(+), 58 deletions(-) diff --git a/c/include/in3/plugin.h b/c/include/in3/plugin.h index 17651aa29..43dceb092 100644 --- a/c/include/in3/plugin.h +++ b/c/include/in3/plugin.h @@ -281,6 +281,7 @@ typedef struct sign_prepare_ctx { typedef enum { SIGN_EC_RAW = 0, /**< sign the data directly */ SIGN_EC_HASH = 1, /**< hash and sign the data */ + SIGN_EC_PREFIX = 2, /**< add Ethereum Signed Message-Proefix, hash and sign the data */ } d_signature_type_t; /** diff --git a/c/include/in3/zksync.h b/c/include/in3/zksync.h index 7b77f1be6..660b1a342 100644 --- a/c/include/in3/zksync.h +++ b/c/include/in3/zksync.h @@ -128,6 +128,11 @@ typedef struct zksync_config { char* proof_create_method; /**< the rpc-method used to create the proof before creating a signature */ } zksync_config_t; +typedef struct valid { + uint64_t from; + uint64_t to; +} zksync_valid_t; + typedef struct pay_criteria { uint_fast32_t payed_nodes; /**< max number of nodes payed at the same time*/ uint64_t max_price_per_hundred_igas; /**< the max price per 100 gas units to accept a payment offer */ @@ -146,6 +151,7 @@ typedef struct { zk_msg_type_t type; /**< message type */ zk_fee_t amount; /**< amount to send */ zk_fee_t fee; /**< ransaction fees */ + zksync_valid_t valid; /**< validity */ } zksync_tx_data_t; /** registers the zksync-plugin in the client */ @@ -167,7 +173,7 @@ NONULL in3_ret_t zksync_emergency_withdraw(zksync_config_t* conf, in3_rpc_handle NONULL in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* req, zksync_config_t* conf); /** creates message data and signs a change_pub_key-message */ -NONULL in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* req, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token); +NONULL in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* req, uint8_t* sync_pub_key, uint32_t nonce, zksync_config_t* conf, zk_fee_t fee, zksync_token_t* token, zksync_valid_t valid); in3_ret_t zksync_musig_sign(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); zk_musig_session_t* zk_musig_session_free(zk_musig_session_t* s); diff --git a/c/src/core/client/plugin.h b/c/src/core/client/plugin.h index 17651aa29..4e6a7524a 100644 --- a/c/src/core/client/plugin.h +++ b/c/src/core/client/plugin.h @@ -279,8 +279,9 @@ typedef struct sign_prepare_ctx { /** type of the requested signature */ typedef enum { - SIGN_EC_RAW = 0, /**< sign the data directly */ - SIGN_EC_HASH = 1, /**< hash and sign the data */ + SIGN_EC_RAW = 0, /**< sign the data directly */ + SIGN_EC_HASH = 1, /**< hash and sign the data */ + SIGN_EC_PREFIX = 2, /**< add Ethereum Signed Message-Proefix, hash and sign the data */ } d_signature_type_t; /** diff --git a/c/src/core/client/request.c b/c/src/core/client/request.c index 974d650cb..5c60cc68e 100644 --- a/c/src/core/client/request.c +++ b/c/src/core/client/request.c @@ -426,7 +426,7 @@ in3_ret_t req_require_signature(in3_req_t* ctx, d_signature_type_t type, bytes_t } // get the signature from required - const char* method = type == SIGN_EC_HASH ? "sign_ec_hash" : "sign_ec_raw"; + const char* method = type == SIGN_EC_HASH ? "sign_ec_hash" : (type == SIGN_EC_PREFIX ? "sign_ec_prefix" : "sign_ec_raw"); in3_req_t* c = req_find_required(ctx, method, NULL); if (c) switch (in3_req_state(c)) { diff --git a/c/src/pay/zksync/zk_helper.c b/c/src/pay/zksync/zk_helper.c index ba401213e..4bf69df49 100644 --- a/c/src/pay/zksync/zk_helper.c +++ b/c/src/pay/zksync/zk_helper.c @@ -188,12 +188,17 @@ in3_ret_t zksync_get_sync_key(zksync_config_t* conf, in3_req_t* ctx, uint8_t* sy } uint8_t* account = NULL; bytes_t signature; - char* message = "\x19" - "Ethereum Signed Message:\n68" - "Access zkSync account.\n\nOnly sign this message for a trusted client!"; + char* message = "Access zkSync account.\n\nOnly sign this message for a trusted client!"; + if (ctx->client->chain.chain_id != CHAIN_ID_MAINNET) { + d_token_t* res = NULL; + TRY(req_send_sub_request(ctx, "eth_chainId", "", NULL, &res, NULL)) + char* tmp = alloca(strlen(message) + 30); + sprintf(tmp, "%s\nChain ID: %d.", message, (int) d_int(res)); + message = tmp; + } TRY(zksync_get_account(conf, ctx, &account)) assert(account); - TRY(req_require_signature(ctx, SIGN_EC_HASH, &signature, bytes((uint8_t*) message, strlen(message)), bytes(account, 20))) + TRY(req_require_signature(ctx, SIGN_EC_PREFIX, &signature, bytes((uint8_t*) message, strlen(message)), bytes(account, 20))) if (signature.len == 65 && signature.data[64] < 2) signature.data[64] += 27; zkcrypto_pk_from_seed(signature, conf->sync_key); diff --git a/c/src/pay/zksync/zk_message.c b/c/src/pay/zksync/zk_message.c index 42d993d36..eb2163823 100644 --- a/c/src/pay/zksync/zk_message.c +++ b/c/src/pay/zksync/zk_message.c @@ -111,9 +111,7 @@ static void create_human_readable_tx_info(sb_t* sb, zksync_tx_data_t* data, char add_amount(sb, data->token, data->amount); sb_add_chars(sb, " "); sb_add_chars(sb, data->token->symbol); - sb_add_rawbytes(sb, "\nTo: 0x", bytes(data->to, 20), 0); - sb_add_chars(sb, "\nNonce: "); - sb_add_int(sb, data->nonce); + sb_add_rawbytes(sb, " to: 0x", bytes(data->to, 20), 0); sb_add_chars(sb, "\nFee: "); add_amount(sb, data->token, data->fee); sb_add_chars(sb, " "); @@ -121,21 +119,10 @@ static void create_human_readable_tx_info(sb_t* sb, zksync_tx_data_t* data, char if (data->token->symbol) #endif sb_add_chars(sb, data->token->symbol); - sb_add_chars(sb, "\nAccount Id: "); - sb_add_int(sb, data->account_id); -} + sb_add_chars(sb, "\nNonce: "); + sb_add_int(sb, data->nonce); -static void create_signed_bytes(sb_t* sb) { - char* PREFIX = "\x19" - "Ethereum Signed Message:\n"; - char len_num[7]; - int l = strlen(PREFIX) + sprintf(len_num, "%d", (int) sb->len); - int len = sb->len; - sb_add_chars(sb, PREFIX); - sb_add_chars(sb, len_num); - memmove(sb->data + l, sb->data, len); - memcpy(sb->data, PREFIX, strlen(PREFIX)); - memcpy(sb->data + l - strlen(len_num), len_num, strlen(len_num)); + in3_log_debug("Human readable message : \n%s\n", sb->data); } static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf, uint8_t* raw, uint8_t* sig, uint32_t* total) { @@ -176,19 +163,22 @@ static in3_ret_t sign_sync_transfer(zksync_tx_data_t* data, in3_req_t* ctx, zksy } in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, zksync_config_t* conf) { + // fix valid.to first if (!data->valid.to) data->valid.to = 0xffffffffl; - char msg_data[216]; - bytes_t signature; - sb_t msg = sb_stack(msg_data); - create_human_readable_tx_info(&msg, data, data->type == ZK_WITHDRAW ? "Withdraw " : "Transfer "); - create_signed_bytes(&msg); + + bytes_t signature = bytes(NULL, 0); + if (data->conf->sign_type != ZK_SIGN_CREATE2) { - TRY(req_require_signature(ctx, SIGN_EC_HASH, &signature, bytes((uint8_t*) msg_data, msg.len), bytes(data->from, 20))) + char msg_data[216]; + sb_t msg = sb_stack(msg_data); + create_human_readable_tx_info(&msg, data, data->type == ZK_WITHDRAW ? "Withdraw " : "Transfer "); + TRY(req_require_signature(ctx, SIGN_EC_PREFIX, &signature, bytes((uint8_t*) msg_data, msg.len), bytes(data->from, 20))) in3_log_debug("zksync_sign_transfer human readable :\n%s\n", msg_data); if (signature.len == 65 && signature.data[64] < 27) signature.data[64] += 27; //because EIP155 chainID = 0 } + // now create the packed sync transfer uint8_t raw[85], sig[96]; uint32_t total = 0; @@ -236,10 +226,7 @@ in3_ret_t zksync_sign_transfer(sb_t* sb, zksync_tx_data_t* data, in3_req_t* ctx, sb_add_chars(sb, "null"); else { sb_add_chars(sb, "{\"type\":\""); - if (data->conf->sign_type == ZK_SIGN_CONTRACT) - sb_add_chars(sb, "EIP1271Signature"); - else - sb_add_chars(sb, "EthereumSignature"); + sb_add_chars(sb, data->conf->sign_type == ZK_SIGN_CONTRACT ? "EIP1271Signature" : "EthereumSignature"); sb_add_rawbytes(sb, "\",\"signature\":\"0x", signature, 0); sb_add_chars(sb, "\"}"); } @@ -284,22 +271,17 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub // now sign it with the new pk TRY(zksync_sign(conf, bytes(sign_msg_bytes, 69), ctx, sig)) - // create human readable message - char msg_data[300]; - uint8_t tmp[8]; - bytes_t signature = bytes(NULL, 0); - sb_t msg = sb_stack(msg_data); - int_to_bytes(nonce, tmp); - int_to_bytes(conf->account_id, tmp + 4); - sb_add_rawbytes(&msg, "Register zkSync pubkey:\n\n", bytes(sync_pub_key, 20), 20); - sb_add_rawbytes(&msg, "\nnonce: 0x", bytes(tmp, 4), 4); - sb_add_rawbytes(&msg, "\naccount id: 0x", bytes(tmp + 4, 4), 4); - sb_add_chars(&msg, "\n\nOnly sign this message for a trusted client!"); - create_signed_bytes(&msg); + // create 2fa-message to be signed with the eth-signer + uint8_t ethmsg[60]; + bytes_t signature = bytes(NULL, 0); + memcpy(ethmsg, sync_pub_key, 20); // pubkeyhash (20) + int_to_bytes(nonce, ethmsg + 20); // nonce (4) + int_to_bytes(conf->account_id, ethmsg + 24); // acount_id (4 bytes) + memset(ethmsg + 28, 0, 32); // msgBatch hash - currently not supported, so 32x0 if (conf->sign_type != ZK_SIGN_CREATE2) { - TRY(req_require_signature(ctx, SIGN_EC_HASH, &signature, bytes((uint8_t*) msg_data, msg.len), bytes(conf->account, 20))) + TRY(req_require_signature(ctx, SIGN_EC_PREFIX, &signature, bytes((uint8_t*) ethmsg, 60), bytes(conf->account, 20))) if (signature.len == 65 && signature.data[64] < 27) signature.data[64] += 27; //because EIP155 chainID = 0 } @@ -328,9 +310,9 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub if (conf->version > 0) { sb_add_chars(sb, ",\"ethAuthData\":{"); if (conf->sign_type == ZK_SIGN_PK) - sb_add_rawbytes(sb, "\"type\":\"EthereumSignature\",\"ethSignature\":\"0x", signature, 0); + sb_add_rawbytes(sb, "\"type\":\"ECDSA\",\"ethSignature\":\"0x", signature, 0); else if (conf->sign_type == ZK_SIGN_CONTRACT) - sb_add_rawbytes(sb, "\"type\":\"OnchainTransaction", signature, 0); + sb_add_rawbytes(sb, "\"type\":\"Onchain", signature, 0); else if (conf->sign_type == ZK_SIGN_CREATE2 && conf->create2) { sb_add_rawbytes(sb, "\"type\":\"CREATE2\",\"creatorAddress\":\"0x", bytes(conf->create2->creator, 20), 0); sb_add_rawbytes(sb, "\",\"saltArg\":\"0x", bytes(conf->create2->salt_arg, 32), 0); @@ -340,13 +322,7 @@ in3_ret_t zksync_sign_change_pub_key(sb_t* sb, in3_req_t* ctx, uint8_t* sync_pub } sb_add_rawbytes(sb, ",\"signature\":{\"pubKey\":\"", bytes(sig, 32), 0); sb_add_rawbytes(sb, "\",\"signature\":\"", bytes(sig + 32, 64), 0); - if (signature.data) { - sb_add_rawbytes(sb, "\"},\"ethSignature\":\"0x", signature, 0); - sb_add_chars(sb, "\"},null,false"); - } - else { - sb_add_chars(sb, "\"}},null,false"); - } + sb_add_chars(sb, "\"}},null,false"); return IN3_OK; } diff --git a/c/src/signer/ledger-nano/signer/ethereum_apdu_client.c b/c/src/signer/ledger-nano/signer/ethereum_apdu_client.c index 98f778c84..7ae73e74e 100644 --- a/c/src/signer/ledger-nano/signer/ethereum_apdu_client.c +++ b/c/src/signer/ledger-nano/signer/ethereum_apdu_client.c @@ -51,6 +51,7 @@ in3_ret_t eth_ledger_sign_txn(void* p_data, in3_plugin_act_t action, void* p_ctx memcpy(hash, sc->message.data, sc->message.len); is_hashed = true; case SIGN_EC_HASH: + case SIGN_EC_PREFIX: if (memcmp(prefix, sc->message.data, strlen(prefix)) == 0) { is_msg = true; } diff --git a/c/src/signer/ledger-nano/signer/ledger_signer.c b/c/src/signer/ledger-nano/signer/ledger_signer.c index efc6d666d..6ba77bebc 100644 --- a/c/src/signer/ledger-nano/signer/ledger_signer.c +++ b/c/src/signer/ledger-nano/signer/ledger_signer.c @@ -86,6 +86,7 @@ in3_ret_t eth_ledger_sign(void* p_data, in3_plugin_act_t action, void* p_ctx) { memcpy(hash, sc->message.data, sc->message.len); is_hashed = true; case SIGN_EC_HASH: + case SIGN_EC_PREFIX: if (!is_hashed) hasher_Raw(HASHER_SHA3K, sc->message.data, sc->message.len, hash); diff --git a/c/src/signer/multisig/multisig.c b/c/src/signer/multisig/multisig.c index 257aa4a47..e5a64fad1 100644 --- a/c/src/signer/multisig/multisig.c +++ b/c/src/signer/multisig/multisig.c @@ -445,6 +445,7 @@ in3_ret_t gs_create_contract_signature(multisig_t* ms, in3_sign_ctx_t* ctx) { else memcpy(hash, ctx->message.data, 32); break; + case SIGN_EC_PREFIX: case SIGN_EC_HASH: { //do we know the domain_seperator? if (memiszero(ms->domain_sep, 32)) { @@ -459,7 +460,18 @@ in3_ret_t gs_create_contract_signature(multisig_t* ms, in3_sign_ctx_t* ctx) { // calculate the message hash according to the GnosisSafe getMessageHash - function. uint8_t tmp[66]; memcpy(tmp, "\x60\xb3\xcb\xf8\xb4\xa2\x23\xd6\x8d\x64\x1b\x3b\x6d\xdf\x9a\x29\x8e\x7f\x33\x71\x0c\xf3\xd3\xa9\xd1\x14\x6b\x5a\x61\x50\xfb\xca", 32); // SAFE_MSG_TYPEHASH - keccak(ctx->message, hash); + + struct SHA3_CTX kctx; + sha3_256_Init(&kctx); + if (ctx->type == SIGN_EC_PREFIX) { + const char* PREFIX = "\x19" + "Ethereum Signed Message:\n"; + sha3_Update(&kctx, (uint8_t*) PREFIX, strlen(PREFIX)); + sha3_Update(&kctx, hash, sprintf((char*) hash, "%d", (int) ctx->message.len)); + } + if (ctx->message.len) sha3_Update(&kctx, ctx->message.data, ctx->message.len); + keccak_Final(&kctx, hash); + if (ms->type == MS_IAMO_SAFE) keccak(bytes(hash, 32), tmp + 32); else diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index cb49990da..163be482d 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -97,6 +97,19 @@ static in3_ret_t eth_sign_pk(void* data, in3_plugin_act_t action, void* action_c switch (ctx->type) { case SIGN_EC_RAW: return ec_sign_pk_raw(ctx->message.data, k->pk, ctx->signature.data); + + case SIGN_EC_PREFIX: { + bytes32_t hash; + struct SHA3_CTX kctx; + sha3_256_Init(&kctx); + const char* PREFIX = "\x19" + "Ethereum Signed Message:\n"; + sha3_Update(&kctx, (uint8_t*) PREFIX, strlen(PREFIX)); + sha3_Update(&kctx, hash, sprintf((char*) hash, "%d", (int) ctx->message.len)); + if (ctx->message.len) sha3_Update(&kctx, ctx->message.data, ctx->message.len); + keccak_Final(&kctx, hash); + return ec_sign_pk_raw(hash, k->pk, ctx->signature.data); + } case SIGN_EC_HASH: return ec_sign_pk_hash(ctx->message.data, ctx->message.len, k->pk, hasher_sha3k, ctx->signature.data); default: diff --git a/wasm/src/wasm.c b/wasm/src/wasm.c index 7ac26281d..4e5dfd87a 100644 --- a/wasm/src/wasm.c +++ b/wasm/src/wasm.c @@ -525,6 +525,18 @@ uint8_t* EMSCRIPTEN_KEEPALIVE ec_sign(bytes32_t pk, d_signature_type_t type, uin uint8_t* dst = malloc(65); int error = -1; switch (type) { + case SIGN_EC_PREFIX: { + bytes32_t hash; + struct SHA3_CTX kctx; + sha3_256_Init(&kctx); + const char* PREFIX = "\x19" "Ethereum Signed Message:\n"; + sha3_Update(&kctx, (uint8_t*) PREFIX, strlen(PREFIX)); + sha3_Update(&kctx, hash, sprintf((char*)hash,"%d", (int)ctx->message.len) ); + if (ctx->message.len) sha3_Update(&kctx, ctx->message.data, ctx->message.len); + keccak_Final(&kctx, hash); + error = ecdsa_sign_digest(&secp256k1, pk, hash, dst, dst + 64, NULL); + break; + } case SIGN_EC_RAW: error = ecdsa_sign_digest(&secp256k1, pk, data, dst, dst + 64, NULL); break; From edd6c62b6fe3bd24adf5db1a5cbdce6ee9056461 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 14:15:32 +0200 Subject: [PATCH 192/221] remove zkeynmc tests in cmd --- c/test/testdata/cmd/zksync_setKey.txt | 87 ------ c/test/testdata/cmd/zksync_setkey_eip1271.txt | 284 ------------------ c/test/testdata/cmd/zksync_setkey_pk.txt | 91 ------ .../testdata/cmd/zksync_setkey_pk_again.txt | 58 ---- c/test/testdata/cmd/zksync_transfer_c2.txt | 93 ------ .../testdata/cmd/zksync_transfer_eip1271.txt | 141 --------- c/test/testdata/cmd/zksync_transfer_pk.txt | 97 ------ c/test/testdata/cmd/zksync_withdraw_c2.txt | 95 ------ .../testdata/cmd/zksync_withdraw_eip1271.txt | 143 --------- c/test/testdata/cmd/zksync_withdraw_pk.txt | 99 ------ 10 files changed, 1188 deletions(-) delete mode 100644 c/test/testdata/cmd/zksync_setKey.txt delete mode 100644 c/test/testdata/cmd/zksync_setkey_eip1271.txt delete mode 100644 c/test/testdata/cmd/zksync_setkey_pk.txt delete mode 100644 c/test/testdata/cmd/zksync_setkey_pk_again.txt delete mode 100644 c/test/testdata/cmd/zksync_transfer_c2.txt delete mode 100644 c/test/testdata/cmd/zksync_transfer_eip1271.txt delete mode 100644 c/test/testdata/cmd/zksync_transfer_pk.txt delete mode 100644 c/test/testdata/cmd/zksync_withdraw_c2.txt delete mode 100644 c/test/testdata/cmd/zksync_withdraw_eip1271.txt delete mode 100644 c/test/testdata/cmd/zksync_withdraw_pk.txt diff --git a/c/test/testdata/cmd/zksync_setKey.txt b/c/test/testdata/cmd/zksync_setKey.txt deleted file mode 100644 index 6100068f2..000000000 --- a/c/test/testdata/cmd/zksync_setKey.txt +++ /dev/null @@ -1,87 +0,0 @@ -:: cmd ./in3 -x -fi ../../c/test/testdata/cmd/zksync_set_key.txt -zks http://localhost:3030 -c http://localhost:8545 -pk 0xe20eb92b34a3c5bd2ef0802a4bc443a90e73fc4a0edc4781446d7b22a44cc5d8 zksync_set_key ETH -debug - -:: time 1608290665 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 0 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 0 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 0 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 0 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x8a91dc2d28b689474298d91899f0c1baf62cb85b"]}] - -:: response account_info 0 http://localhost:3030 0 82 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x8a91dc2d28b689474298d91899f0c1baf62cb85b", - "id":1, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"972447700001000001" - }, - "nonce":28, - "pubKeyHash":"sync:87b8682587abb487584801ca4546c4b8f8173c11" - }, - "verified":{ - "balances":{ - "ETH":"972447700001000001" - }, - "nonce":28, - "pubKeyHash":"sync:87b8682587abb487584801ca4546c4b8f8173c11" - } - }, - "id":2 -}] - - -:: cache zksync_tokens_69f5 1 -03004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f00000045544800000000001200000000000000000000000000000000000000000004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":[{"ChangePubKey":{"onchainPubkeyAuth":false}},"0x8a91dc2d28b689474298d91899f0c1baf62cb85b","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 2 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":{ - "ChangePubKey":{ - "onchainPubkeyAuth":false - } - }, - "gasTxAmount":"10000", - "gasPriceWei":"9000000000", - "gasFee":"90000000000000", - "zkpFee":"31465100362113", - "totalFee":"121400000000000" - }, - "id":3 -}] - - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"ChangePubKey","accountId":1,"account":"0x8a91dc2d28b689474298d91899f0c1baf62cb85b","newPkHash":"sync:20ae0f0ef7780f289ade282a466ad287969a1253","feeToken":0,"fee":121400000000000,"nonce":28,"signature":{"pubKey":"3746e7a4dbbb25ea36a3d20c2431775f69b737b1e0a173803e9cf74570b5dc86","signature":"3756ed60d8c323a81d070e1f8857fcb18a53eddbb9871d3c90a01599ddb470a63190fe165251c988338865049b97fafd9935be818a78fe9921453738f8536904"},"ethSignature":"0x836ae105a27a65deb4f688e6cdcbe71928bc6bb7599facce2281adcde8504052374a81ab3944c039ca56dfe98e7e9348c1f600f374c779c180bf30567405a9101b"},null,false]}] - -:: response tx_submit 0 http://localhost:3030 0 41 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:489f5f95f2dcaef4f5534d62d8646d2e9891a31b409f1a8ba9b581886e7177c6", - "id":4 -}] - - -:: result -sync:20ae0f0ef7780f289ade282a466ad287969a1253 \ No newline at end of file diff --git a/c/test/testdata/cmd/zksync_setkey_eip1271.txt b/c/test/testdata/cmd/zksync_setkey_eip1271.txt deleted file mode 100644 index e45d9fafb..000000000 --- a/c/test/testdata/cmd/zksync_setkey_eip1271.txt +++ /dev/null @@ -1,284 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xe20eb92b34a3c5bd2ef0802a4bc443a90e73fc4a0edc4781446d7b22a44cc5d8 -c http://localhost:8545 -fi zksync_setkey_eip1271.txt -ms 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zka 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zkat contract zksync_set_key ETH - -:: time 1610970472 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4"]}] - -:: response account_info 0 http://localhost:3030 0 153 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4", - "id":6, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"4000000000000000000" - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:8545 - [{"id":3,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa3f4df7e"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 28 -[{ - "jsonrpc":"2.0", - "id":3, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000949414d4f20536166650000000000000000000000000000000000000000000000" -}] - - -:: request http://localhost:8545 - [{"id":4,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xf698da25"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":4, - "result":"0x4846ae0437a0613c8742fb643c665ce1a680fbab2a296b40bc5d09e317c13acb" -}] - - -:: request http://localhost:8545 - [{"id":5,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa0e67e2b"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":5, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000072876ced28f246e1d1e44b38f7825c999a951ea70000000000000000000000008a91dc2d28b689474298d91899f0c1baf62cb85b" -}] - - -:: request http://localhost:8545 - [{"id":6,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xe75235b8"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 11 -[{ - "jsonrpc":"2.0", - "id":6, - "result":"0x0000000000000000000000000000000000000000000000000000000000000001" -}] - - -:: cache zksync_contracts_69f5 1 -9ab6772bd7789d2865a27da5a3f7f265bc3ea39d9534a57289b8f1b8dcb6b2722c803f2969a8c0d1 - -:: request http://localhost:8545 - [{"id":7,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x9ab6772bd7789d2865a27da5a3f7f265bc3ea39d","data":"0x8ae20dc90000000000000000000000007ff5c6fab254833c037ad23ca32e2b2b2c6083a40000000000000000000000000000000000000000000000000000000000000000"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 14 -[{ - "jsonrpc":"2.0", - "id":7, - "result":"0x0000000000000000000000000000000000000000000000000000000000000000" -}] - - -:: request http://localhost:8545 - [{"id":10,"jsonrpc":"2.0","method":"eth_chainId","params":[]}] - -:: response eth_chainId 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":10, - "result":"0x9" -}] - - -:: request http://localhost:8545 - [{"id":11,"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0x8a91dc2d28b689474298d91899f0c1baf62cb85b","latest"]}] - -:: response eth_getTransactionCount 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":11, - "result":"0x37" -}] - - -:: request http://localhost:8545 - [{"id":12,"jsonrpc":"2.0","method":"eth_gasPrice","params":[]}] - -:: response eth_gasPrice 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":12, - "result":"0x3b9aca00" -}] - - -:: request http://localhost:8545 - [{"id":13,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xaffed0e0"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 20 -[{ - "jsonrpc":"2.0", - "id":13, - "result":"0x0000000000000000000000000000000000000000000000000000000000000001" -}] - - -:: request http://localhost:8545 - [{"id":14,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xd8d11f780000000000000000000000009ab6772bd7789d2865a27da5a3f7f265bc3ea39d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000084595a5ebc0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000142634ea722a88f1d178fe4b1b63c2e91a7089cfac00000000000000000000000000000000000000000000000000000000000000000000000000000000"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 13 -[{ - "jsonrpc":"2.0", - "id":14, - "result":"0x3981ed8b93dd5af67e8c2d45f013bb70c9615665943629eba7fe99b7beb07d6d" -}] - - -:: request http://localhost:8545 - [{"id":9,"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xf902ea37843b9aca008307a120947ff5c6fab254833c037ad23ca32e2b2b2c6083a480b902846a7612020000000000000000000000009ab6772bd7789d2865a27da5a3f7f265bc3ea39d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030d400000000000000000000000000000000000000000000000000000000000030d40000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000084595a5ebc0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000142634ea722a88f1d178fe4b1b63c2e91a7089cfac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000008a91dc2d28b689474298d91899f0c1baf62cb85b0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000036a075df23ee769da112b0207b067fb560cd689d248ea9ee8d96a3ae55f1a1d21bc7a04d16290ada4c89ccd9cc56174706532a75e0c96988670e1d346a3214cf6cd535"]}] - -:: response eth_sendRawTransaction 0 http://localhost:8545 0 73 -[{ - "jsonrpc":"2.0", - "id":9, - "result":"0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef" -}] - - -:: request http://localhost:8545 - [{"id":15,"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef"]}] - -:: response eth_getTransactionReceipt 0 http://localhost:8545 0 52 -[{ - "jsonrpc":"2.0", - "id":15, - "result":null -}] - - -:: request http://localhost:8545 - [{"id":16,"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef"]}] - -:: response eth_getTransactionReceipt 0 http://localhost:8545 0 11 -[{ - "jsonrpc":"2.0", - "id":16, - "result":null -}] - - -:: request http://localhost:8545 - [{"id":17,"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef"]}] - -:: response eth_getTransactionReceipt 0 http://localhost:8545 0 13 -[{ - "jsonrpc":"2.0", - "id":17, - "result":{ - "blockHash":"0x5c088aa63127ea9800ec3942b26a06a3d456830b240e14ac5394204bbbf9d685", - "blockNumber":"0x27719", - "contractAddress":null, - "cumulativeGasUsed":"0x154d4", - "from":"0x8a91dc2d28b689474298d91899f0c1baf62cb85b", - "gasUsed":"0x154d4", - "logs":[{ - "address":"0x9ab6772bd7789d2865a27da5a3f7f265bc3ea39d", - "topics":["0x9ea39b45a0cc96a2139996ec8dd30326216111249750781e563ae27c31ae8766", - "0x0000000000000000000000007ff5c6fab254833c037ad23ca32e2b2b2c6083a4"], - "data":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000142634ea722a88f1d178fe4b1b63c2e91a7089cfac000000000000000000000000", - "blockNumber":"0x27719", - "transactionHash":"0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef", - "transactionIndex":"0x0", - "blockHash":"0x5c088aa63127ea9800ec3942b26a06a3d456830b240e14ac5394204bbbf9d685", - "logIndex":"0x0", - "removed":false - }, - { - "address":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4", - "topics":["0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e", - "0x3981ed8b93dd5af67e8c2d45f013bb70c9615665943629eba7fe99b7beb07d6d"], - "data":"0x0000000000000000000000000000000000000000000000000000d48b9710c000", - "blockNumber":"0x27719", - "transactionHash":"0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef", - "transactionIndex":"0x0", - "blockHash":"0x5c088aa63127ea9800ec3942b26a06a3d456830b240e14ac5394204bbbf9d685", - "logIndex":"0x1", - "removed":false - }], - "logsBloom":"0x00000000400000000000000000000000000000000000000000000020040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002100400000000000000000000080000000000000000000000000000000000000000100400000000000000000000000000000000000000000000000000040000000000000000004000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000002000000000000000000000000000000004080000000200000000", - "status":"0x1", - "to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4", - "transactionHash":"0x537799a241cdb5eea7e3d373cb0c7924291db063f748bbea1eaaff46ddacc7ef", - "transactionIndex":"0x0" - } -}] - - -:: request http://localhost:3030 - [{"id":18,"jsonrpc":"2.0","method":"get_tx_fee","params":[{"ChangePubKey":{"onchainPubkeyAuth":true}},"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 201 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":{ - "ChangePubKey":{ - "onchainPubkeyAuth":true - } - }, - "gasTxAmount":"9929", - "gasPriceWei":"1000000000", - "gasFee":"9929000000000", - "zkpFee":"30801359919309", - "totalFee":"40700000000000" - }, - "id":18 -}] - - -:: request http://localhost:3030 - [{"id":19,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"ChangePubKey","accountId":6,"account":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","newPkHash":"sync:2634ea722a88f1d178fe4b1b63c2e91a7089cfac","feeToken":0,"fee":40700000000000,"nonce":0,"signature":{"pubKey":"9210334638e3c73a45accc0f791339fab57bd0714a2c7295c252f270c5a24805","signature":"7d9d091313274db6d625c8128916b4a3625ad361d7499ec8689f79d80eaf1da7c0e4c9982e01b09fab74478db461e187ab8ac624b8ad1bb254c5d37042802601"},"ethSignature":null},null,false]}] - -:: response tx_submit 0 http://localhost:3030 0 130 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:10bcbaf339f299a74beab3c82b513fce633153adc5dd5acdafe8b8163ca521e7", - "id":19 -}] - - -:: result -sync:2634ea722a88f1d178fe4b1b63c2e91a7089cfac diff --git a/c/test/testdata/cmd/zksync_setkey_pk.txt b/c/test/testdata/cmd/zksync_setkey_pk.txt deleted file mode 100644 index cee40c904..000000000 --- a/c/test/testdata/cmd/zksync_setkey_pk.txt +++ /dev/null @@ -1,91 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xc073624ce79d35f60581134500771cecf21c34e07f5f599033cabaceeb187fef -c http://localhost:8545 -fi zksync_setkey_pk.txt zksync_set_key ETH -debug - -:: time 1610972402 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x3b98be46d348d45ddcd3343f7fdb21373e7f197c"]}] - -:: response account_info 0 http://localhost:3030 0 414 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c", - "id":8, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"1990493664000000000" - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":[{"ChangePubKey":{"onchainPubkeyAuth":false}},"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 116 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":{ - "ChangePubKey":{ - "onchainPubkeyAuth":false - } - }, - "gasTxAmount":"10000", - "gasPriceWei":"1000000000", - "gasFee":"10000000000000", - "zkpFee":"27514315249288", - "totalFee":"37500000000000" - }, - "id":3 -}] - - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"ChangePubKey","accountId":8,"account":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","newPkHash":"sync:9d9625572548e7fe4ba248ac60c0c7fdaca432cc","feeToken":0,"fee":37500000000000,"nonce":0,"signature":{"pubKey":"33624d532da9ec053a183287a59f0af93750fa98f4c6c43f1beec1381bf03d12","signature":"58e7802d1b4781952f3f29c8d6474c7946a812bef54154f80636141164b7c79329dd1bdccc03b556ac0dd2fca4d9df3dc7c1a72a974f37af349d248fa9fa7002"},"ethSignature":"0x21a21b5d0942ba1e255c3ca9ae6f7c268504cac25a966ed279765c3be10e1a2e5427ee1cdb8100f46b8fb522789012e0d494e585aadf682e71ff9acdab0a37e31c"},null,false]}] - -:: response tx_submit 0 http://localhost:3030 0 316 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:d0a01ac86c19ccccbf1d7b8abe4dc50cd5c21ec337932635a5d62cfb56636f0d", - "id":4 -}] - - -:: result -sync:9d9625572548e7fe4ba248ac60c0c7fdaca432cc diff --git a/c/test/testdata/cmd/zksync_setkey_pk_again.txt b/c/test/testdata/cmd/zksync_setkey_pk_again.txt deleted file mode 100644 index 50757415c..000000000 --- a/c/test/testdata/cmd/zksync_setkey_pk_again.txt +++ /dev/null @@ -1,58 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xc073624ce79d35f60581134500771cecf21c34e07f5f599033cabaceeb187fef -c http://localhost:8545 -fi zksync_setkey_pk_again.txt zksync_set_key ETH -debug - -:: time 1610972451 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x3b98be46d348d45ddcd3343f7fdb21373e7f197c"]}] - -:: response account_info 0 http://localhost:3030 0 208 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c", - "id":8, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"1990456164000000000" - }, - "nonce":1, - "pubKeyHash":"sync:9d9625572548e7fe4ba248ac60c0c7fdaca432cc" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: result -Error: Signer key is already set diff --git a/c/test/testdata/cmd/zksync_transfer_c2.txt b/c/test/testdata/cmd/zksync_transfer_c2.txt deleted file mode 100644 index 40d9f118c..000000000 --- a/c/test/testdata/cmd/zksync_transfer_c2.txt +++ /dev/null @@ -1,93 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -c http://localhost:8545 -fi zksync_transfer_c2.txt -zka 0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 -zkat create2 -zsk 0xd818beb367732ed0bc2ada1750fcce827040edf96ea3cdacf420b5c3cb1456df zksync_transfer 0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec 0.1eth ETH - -:: time 1611139221 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 0 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 0 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 0 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 0 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02"]}] - -:: response account_info 0 http://localhost:3030 0 255 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02", - "id":7, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"1499883400000000000" - }, - "nonce":1, - "pubKeyHash":"sync:41b98bc1f219e0defd42078d018826f4404f801c" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 0 - -:: cache zksync_tokens_69f5 1 -010044414900000000001264e9e65f1cee1fa5071d0075cd211e7b7274a444000300424154000000000012a41da0108ab9875d60169b8a9cd4c8a13b3b2ef20000004554480000000000120000000000000000000000000000000000000000000200774254430000000008cb18f9f65af976000931ca251741068e6aabbd2f0004004d4c545400000000124368e824754a7de8d8a82db5725c48a1e191cbc600 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":["Transfer","0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 84 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"TransferToNew", - "gasTxAmount":"6862", - "gasPriceWei":"9000000000", - "gasFee":"61758000000000", - "zkpFee":"32336663980566", - "totalFee":"94000000000000" - }, - "id":3 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Transfer","accountId":7,"from":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02","to":"0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","token":0,"amount":100000000000000000,"fee":94000000000000,"nonce":1,"signature":{"pubKey":"7232c12955637f5fb5495ab9279bba0a0830bc48f72c6e0c380a2fe40888c8ac","signature":"c8bbd3befec8a6581381398b91166d8405a372f5ff43d773c017f422e3171786191a9f8abccda8c5542a487de50fd6d4847ec402331abdbf3547647274b0be05"}},{"type":"EthereumSignature","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b"}]}] - -:: response tx_submit 0 http://localhost:3030 0 335 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:3390ff0452e19593166cc6c4883b46a3a78c82fbde01a96b9ae03bf7f74a7c28", - "id":4 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: result -{"type":"Transfer","accountId":7,"from":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02","to":"0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","token":0,"amount":100000000000000000,"fee":94000000000000,"nonce":1,"txHash":"sync-tx:3390ff0452e19593166cc6c4883b46a3a78c82fbde01a96b9ae03bf7f74a7c28"} diff --git a/c/test/testdata/cmd/zksync_transfer_eip1271.txt b/c/test/testdata/cmd/zksync_transfer_eip1271.txt deleted file mode 100644 index 4454f9dc8..000000000 --- a/c/test/testdata/cmd/zksync_transfer_eip1271.txt +++ /dev/null @@ -1,141 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xe20eb92b34a3c5bd2ef0802a4bc443a90e73fc4a0edc4781446d7b22a44cc5d8 -c http://localhost:8545 -fi zksync_transfer_eip1271.txt -ms 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zka 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zkat contract zksync_transfer 0xab6ff744cf1276a78460e93972d22725abd3e095 9433236000000000 ETH - -:: time 1610970586 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:8545 - [{"id":2,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa3f4df7e"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 18 -[{ - "jsonrpc":"2.0", - "id":2, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000949414d4f20536166650000000000000000000000000000000000000000000000" -}] - - -:: request http://localhost:8545 - [{"id":3,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xf698da25"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":3, - "result":"0x4846ae0437a0613c8742fb643c665ce1a680fbab2a296b40bc5d09e317c13acb" -}] - - -:: request http://localhost:8545 - [{"id":4,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa0e67e2b"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 13 -[{ - "jsonrpc":"2.0", - "id":4, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000072876ced28f246e1d1e44b38f7825c999a951ea70000000000000000000000008a91dc2d28b689474298d91899f0c1baf62cb85b" -}] - - -:: request http://localhost:8545 - [{"id":5,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xe75235b8"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 9 -[{ - "jsonrpc":"2.0", - "id":5, - "result":"0x0000000000000000000000000000000000000000000000000000000000000001" -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 0 - -:: request http://localhost:3030 - [{"id":6,"jsonrpc":"2.0","method":"account_info","params":["0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4"]}] - -:: response account_info 0 http://localhost:3030 0 559 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4", - "id":6, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"3999959300000000000" - }, - "nonce":1, - "pubKeyHash":"sync:2634ea722a88f1d178fe4b1b63c2e91a7089cfac" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":6 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 0 - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":7,"jsonrpc":"2.0","method":"get_tx_fee","params":["Transfer","0xab6ff744cf1276a78460e93972d22725abd3e095","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 57 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"TransferToNew", - "gasTxAmount":"1650", - "gasPriceWei":"1000000000", - "gasFee":"1650000000000", - "zkpFee":"30801359919309", - "totalFee":"32400000000000" - }, - "id":7 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: request http://localhost:3030 - [{"id":8,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Transfer","accountId":6,"from":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","to":"0xab6ff744cf1276a78460e93972d22725abd3e095","token":0,"amount":9433236000000000,"fee":32400000000000,"nonce":1,"signature":{"pubKey":"9210334638e3c73a45accc0f791339fab57bd0714a2c7295c252f270c5a24805","signature":"c04dbdc1c668fafb162584ec816ff6ae94db7d598c4bfc69ca2f93411ff922b089cd1cdeb3a99266bffb37d96a9183088139c9b0a01dd039c9fab5346b9eb204"}},{"type":"EIP1271Signature","signature":"0x8dda163e0af2140d0034eefcc8c37262a23cc4a7cfa12db2aeb6d199534513b8412876637b12d104a61d59af49e11e26a96cc798fff3361346cd602f508951681c"}]}] - -:: response tx_submit 0 http://localhost:3030 0 668 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:0742270d982f9296b79c85e5d83148e581509e823a4c60da3aa5dfa662b7451b", - "id":8 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: result -{"type":"Transfer","accountId":6,"from":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","to":"0xab6ff744cf1276a78460e93972d22725abd3e095","token":0,"amount":9433236000000000,"fee":32400000000000,"nonce":1,"txHash":"sync-tx:0742270d982f9296b79c85e5d83148e581509e823a4c60da3aa5dfa662b7451b"} diff --git a/c/test/testdata/cmd/zksync_transfer_pk.txt b/c/test/testdata/cmd/zksync_transfer_pk.txt deleted file mode 100644 index a13a880cf..000000000 --- a/c/test/testdata/cmd/zksync_transfer_pk.txt +++ /dev/null @@ -1,97 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xc073624ce79d35f60581134500771cecf21c34e07f5f599033cabaceeb187fef -c http://localhost:8545 -fi zksync_transfer_pk.txt zksync_transfer 0x8a91dc2d28b689474298d91899f0c1baf62cb85b 990493664000000000 ETH - -:: time 1610972571 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 0 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x3b98be46d348d45ddcd3343f7fdb21373e7f197c"]}] - -:: response account_info 0 http://localhost:3030 0 436 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c", - "id":8, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"1990456164000000000" - }, - "nonce":1, - "pubKeyHash":"sync:9d9625572548e7fe4ba248ac60c0c7fdaca432cc" - }, - "verified":{ - "balances":{ - "ETH":"1990493664000000000" - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 0 - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":["Transfer","0x8a91dc2d28b689474298d91899f0c1baf62cb85b","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 536 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"Transfer", - "gasTxAmount":"550", - "gasPriceWei":"1000000000", - "gasFee":"550000000000", - "zkpFee":"9171438416430", - "totalFee":"9720000000000" - }, - "id":3 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Transfer","accountId":8,"from":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","to":"0x8a91dc2d28b689474298d91899f0c1baf62cb85b","token":0,"amount":990493664000000000,"fee":9720000000000,"nonce":1,"signature":{"pubKey":"33624d532da9ec053a183287a59f0af93750fa98f4c6c43f1beec1381bf03d12","signature":"04795df4f451f7ae26a17c76530f910b44d0835f29984a2fb0ef512271514a16c911fd0642979a2d67f9dd2c137a2e53d4030e585f3436e65930a389ae5dfe01"}},{"type":"EthereumSignature","signature":"0xfa944c2cdf233ff6a423e43cc1720bdd802f48f4ad45e3607e910e7ae75ecd2c6d5d7f16ec1ff6c428a908ac0ccd67a7db972f9c3b31b3b405f4b73e13686b731b"}]}] - -:: response tx_submit 0 http://localhost:3030 0 572 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:343c96affe05c9b6c65d0c0eb8a1cf5a5a6c9b3f30dee85011c433db5680db60", - "id":4 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: result -{"type":"Transfer","accountId":8,"from":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","to":"0x8a91dc2d28b689474298d91899f0c1baf62cb85b","token":0,"amount":990493664000000000,"fee":9720000000000,"nonce":1,"txHash":"sync-tx:343c96affe05c9b6c65d0c0eb8a1cf5a5a6c9b3f30dee85011c433db5680db60"} diff --git a/c/test/testdata/cmd/zksync_withdraw_c2.txt b/c/test/testdata/cmd/zksync_withdraw_c2.txt deleted file mode 100644 index 6af2a6169..000000000 --- a/c/test/testdata/cmd/zksync_withdraw_c2.txt +++ /dev/null @@ -1,95 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -c http://localhost:8545 -fi zksync_withdraw_c2.txt -zka 0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 -zkat create2 -zsk 0xd818beb367732ed0bc2ada1750fcce827040edf96ea3cdacf420b5c3cb1456df zksync_withdraw 0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec 0.05eth ETH - -:: time 1611139373 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 0 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 0 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 0 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 0 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: cache zksync_tokens_69f5 1 -010044414900000000001264e9e65f1cee1fa5071d0075cd211e7b7274a444000300424154000000000012a41da0108ab9875d60169b8a9cd4c8a13b3b2ef20000004554480000000000120000000000000000000000000000000000000000000200774254430000000008cb18f9f65af976000931ca251741068e6aabbd2f0004004d4c545400000000124368e824754a7de8d8a82db5725c48a1e191cbc600 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02"]}] - -:: response account_info 0 http://localhost:3030 0 255 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02", - "id":7, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"1399789400000000000" - }, - "nonce":2, - "pubKeyHash":"sync:41b98bc1f219e0defd42078d018826f4404f801c" - }, - "verified":{ - "balances":{ - - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":["Withdraw","0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 67 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"Withdraw", - "gasTxAmount":"96991", - "gasPriceWei":"9000000000", - "gasFee":"872919000000000", - "zkpFee":"32336663980566", - "totalFee":"905000000000000" - }, - "id":3 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Withdraw","accountId":7,"from":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02","to":"0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","token":0,"amount":50000000000000000,"fee":905000000000000,"nonce":2,"signature":{"pubKey":"7232c12955637f5fb5495ab9279bba0a0830bc48f72c6e0c380a2fe40888c8ac","signature":"fb770eb76ac492d6a01e996fdff52fee747f057579a876866cfd695de44ac6169f34e1481b31f2379f90a42f9d10825239c496c978b85d3fe42dc2303a996a03"}},{"type":"EthereumSignature","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b"}]}] - -:: response tx_submit 0 http://localhost:3030 0 52 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:bd574e8b0d8f93a205801cdb1a6a15521e089b3b927436b22a7f9a24625c407e", - "id":4 -}] - - -:: cache zksync_ac8f6883b78d71ac2871f4b01d6fc5e047ccecfd02 1 -00000007 - -:: result -{"type":"Withdraw","accountId":7,"from":"0x8f6883b78d71ac2871f4b01d6fc5e047ccecfd02","to":"0xce93a4561fe6445653a8f6e4ff73c971ce1e9eec","token":0,"amount":50000000000000000,"fee":905000000000000,"nonce":2,"txHash":"sync-tx:bd574e8b0d8f93a205801cdb1a6a15521e089b3b927436b22a7f9a24625c407e"} diff --git a/c/test/testdata/cmd/zksync_withdraw_eip1271.txt b/c/test/testdata/cmd/zksync_withdraw_eip1271.txt deleted file mode 100644 index 40261189d..000000000 --- a/c/test/testdata/cmd/zksync_withdraw_eip1271.txt +++ /dev/null @@ -1,143 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xe20eb92b34a3c5bd2ef0802a4bc443a90e73fc4a0edc4781446d7b22a44cc5d8 -c http://localhost:8545 -fi zksync_withdraw_eip1271.txt -ms 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zka 0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 -zkat contract zksync_withdraw 0xab6ff744cf1276a78460e93972d22725abd3e095 1990493664000000000 ETH - -:: time 1610970705 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: request http://localhost:8545 - [{"id":2,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa3f4df7e"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 121 -[{ - "jsonrpc":"2.0", - "id":2, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000949414d4f20536166650000000000000000000000000000000000000000000000" -}] - - -:: request http://localhost:8545 - [{"id":3,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xf698da25"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 93 -[{ - "jsonrpc":"2.0", - "id":3, - "result":"0x4846ae0437a0613c8742fb643c665ce1a680fbab2a296b40bc5d09e317c13acb" -}] - - -:: request http://localhost:8545 - [{"id":4,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xa0e67e2b"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 10 -[{ - "jsonrpc":"2.0", - "id":4, - "result":"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000072876ced28f246e1d1e44b38f7825c999a951ea70000000000000000000000008a91dc2d28b689474298d91899f0c1baf62cb85b" -}] - - -:: request http://localhost:8545 - [{"id":5,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","data":"0xe75235b8"},"latest"]}] - -:: response eth_call 0 http://localhost:8545 0 12 -[{ - "jsonrpc":"2.0", - "id":5, - "result":"0x0000000000000000000000000000000000000000000000000000000000000001" -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":6,"jsonrpc":"2.0","method":"account_info","params":["0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4"]}] - -:: response account_info 0 http://localhost:3030 0 332 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4", - "id":6, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"3990493664000000000" - }, - "nonce":2, - "pubKeyHash":"sync:2634ea722a88f1d178fe4b1b63c2e91a7089cfac" - }, - "verified":{ - "balances":{ - "ETH":"4000000000000000000" - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":6 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: request http://localhost:3030 - [{"id":7,"jsonrpc":"2.0","method":"get_tx_fee","params":["Withdraw","0xab6ff744cf1276a78460e93972d22725abd3e095","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 48 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"Withdraw", - "gasTxAmount":"45000", - "gasPriceWei":"1000000000", - "gasFee":"45000000000000", - "zkpFee":"30801359919309", - "totalFee":"75800000000000" - }, - "id":7 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: request http://localhost:3030 - [{"id":8,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Withdraw","accountId":6,"from":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","to":"0xab6ff744cf1276a78460e93972d22725abd3e095","token":0,"amount":1990493664000000000,"fee":75800000000000,"nonce":2,"signature":{"pubKey":"9210334638e3c73a45accc0f791339fab57bd0714a2c7295c252f270c5a24805","signature":"dc799017375a065c3bcd8185990a46e6b73612de1eebde429579a1538755e00b3fbd0bdcc3e3ef2297956c48c12c395abd35cb1b0b7c778c396b71f25a2c0703"}},{"type":"EIP1271Signature","signature":"0x7fe6d8e1b56998d1a451854e7417dd546a0e832c20c3433b020cb61200c6847f4fe99e3eb755b26f904135b6643e1c99e6c86488a18cd7bcbb813802586323c61b"}]}] - -:: response tx_submit 0 http://localhost:3030 0 95 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:e3319b79867e81d7b928d19b526b26580d7f0dff82f911cd73c461847238db68", - "id":8 -}] - - -:: cache zksync_ac7ff5c6fab254833c037ad23ca32e2b2b2c6083a4 1 -00000006 - -:: result -{"type":"Withdraw","accountId":6,"from":"0x7ff5c6fab254833c037ad23ca32e2b2b2c6083a4","to":"0xab6ff744cf1276a78460e93972d22725abd3e095","token":0,"amount":1990493664000000000,"fee":75800000000000,"nonce":2,"txHash":"sync-tx:e3319b79867e81d7b928d19b526b26580d7f0dff82f911cd73c461847238db68"} diff --git a/c/test/testdata/cmd/zksync_withdraw_pk.txt b/c/test/testdata/cmd/zksync_withdraw_pk.txt deleted file mode 100644 index 4270413c2..000000000 --- a/c/test/testdata/cmd/zksync_withdraw_pk.txt +++ /dev/null @@ -1,99 +0,0 @@ -:: cmd in3 -x -zks http://localhost:3030 -pk 0xc073624ce79d35f60581134500771cecf21c34e07f5f599033cabaceeb187fef -c http://localhost:8545 -fi zksync_withdraw_pk.txt zksync_withdraw 0xec8b8b4e05f647b36fa31d76273a7dc2860d0e73 90493664000000000 ETH - -:: time 1610972724 - -:: cache nodelist_1_0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f 1 -06ac1b824795e1eb1f6e609fe0da9b9af8beaab60f0000000000aa13280000001801000000cc000000000000000000000001000000ba0000000000000000000000c301000026c106000000000000000000c301000014c306000000000000000000c301000011ce06000000000000000000c2010000254305000000000000000000c20100004e9b05000000000000000000c2010000d08806000000000000000000c201000005d70600000000000000000002000000f42700000000000000000000c301000006b806000000000000000000010000004a0600000000000000000000c2010000678207000000000000000000c3010000bee107000138bd5f00000000c20100008bec07000000000000000000c2010000e76607000000000000000000c30100009f4907000000000000000000c3010000c9d10700d77bc75f00000000c3010000e0d307000000000000000000c301000010e207000000000000000000c20100008d8a07000000000000000000c3010000080c08000000000000000000c3010000e4ea0e000000000000000000c301000017de07005413a15f0000000000000001000000000e043da61725000000000006000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d310000000001000000011be4f459be89000000000006000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3200000000010000000245871874b4b5000000000006000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d330000000001000000038aeaa9f6f9a9000000000006000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000010000000415b1ccfb8391000100000006000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6d61696e6e65742f6e642d3500000000010000000503782dace9d9000000000006000001dde9a1f583c6591566b0cda30dd2a647126d1ce0c2687474703a2f2f6574682d6d61696e6e65742d30312e696e63756265642d6e6f64652e64653a38353030000000000100000006016345785d8a00000000000a000001d1cff39dbe511bcf14b65e4030b3d8700e0ed67cea68747470733a2f2f696e332d6e6f64652d312e6b65696c2d636f6e6e6563742e636f6d000000000100000007002386f26fc100000000000a000001d9792cc04f89b012ac1f98c19b7281fbda8a3e1a9268747470733a2f2f696e332d6e6f64652d66726f6d2e7370616365000000000100000008002386f26fc100000000000a000001d1b8cf3f02c24ca897b157a34019711679c6e556a868747470733a2f2f696e332e696f74656e61626c65722e636f6d000000000100000009002386f26fc100000000000f000001d977a4a0e80d7786dec85e3087cc1c6ac3802af9cd68747470733a2f2f696e63756265642e6f6e6c696e6500000000010000000a002386f26fc100000000000f000001d9591761898ba2dfcf3b230bd3ab7d0de0c4ef168f68747470733a2f2f696e332e696e64656e776f6c6b656e2e7465636800000000010000000b002386f26fc100000000000f000001d90cea2ff03adcfa047e8f54f98d41d9147c3ccd4d68747470733a2f2f696e332d672e6f70656e2d646e612e646500000000010000000c002386f26fc100000000000a000001d1510ee7f6f198e018e3529164da2473a96eeb3dc868747470733a2f2f303030312e6d61696e6e65742e696e332e616e79626c6f636b2e746f6f6c7300000000010000000d002386f26fc100000000000a000001d14323d321a39ed4a197524c6acd18c072f753c1b068747470733a2f2f696e332d7061726974792e696f74656e61626c65722e636f6d2f00000000010000000e002386f26fc100000000000a000001d18db016dbdc03e76990adda627aab64db8106be4b68747470733a2f2f696e332d676574682e696f74656e61626c65722e636f6d2f00000000010000000f002386f26fc100000000000a000001d119580b648bb23163136b583ff5f56657fffb661068747470733a2f2f696e332d696e667572612e696f74656e61626c65722e636f6d2f000000000100000010002386f26fc1000000000006000001d965b9464bc41dc35534f8b6ea5108f4905161efd268747470733a2f2f696e336e6f2e6465000000000100000011002386f26fc1000000000006000001d91389e3b68bbef358e4ee6fabf94d3c884deda37668747470733a2f2f6c657473696e63756265642e636f6d000000000100000012002386f26fc100000000000f000001d900a329c0648769a73afac7f9381e08fb43dbea7268747470733a2f2f696e336e6f64652e636f6d000000000100000013002386f26fc1000000000006000001d9ccd12a2222995e62eca64426989c2688d828aa4768747470733a2f2f636861696e642e64652f6574682f6d61696e6e657431000000000100000014002386f26fc100000000000a000001d16d172460c0303736c2fd4a329664fe03c2f0951268747470733a2f2f696e332e74756334372e78797a000000000100000015002386f26fc1000000000006000001d96e314c4c7b5ae5c6f49aea2d90a1d083abab045d68747470733a2f2f696e332e61686e656e706f737465722e6465000000000100000016002386f26fc100000000000a000001d1daaf752eabf0dc0e8b0ef00045efed6cfda727d668747470733a2f2f696e332e7468656d7973746572696f7573636c6f776e2e636f6d000000000100000017002386f26fc100000000000a000001d150ac4400652a4a0b29162cf7eac173bd6a67162768747470733a2f2f626974636875722e63682f696e332f6d61696e6e657400000000012813aa00000000001905cf372e0a06cef38dfa96691b336e4a1328ed9c93a769aac93db7328d1828 - -:: cache nodelist_5_0x5f51e413581dd76759e9eed51e63d14c8d1379c8 1 -065f51e413581dd76759e9eed51e63d14c8d1379c80000000000353ec000000008020000000302000000000000000000000400000077050000c57cc75f0000000079170000cfbb0b0000000000000000007a17000013f50b00c57cc75f000000007a1700003ae10b00c57cc75f00000000771700006a9222000000000000000000771700005d341300000000000000000079170000b91d1600487ec75f000000000000000100000000002386f26fc1000000000000000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d31000000000100000001002386f26fc1000000000000000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d32000000000100000002002386f26fc1000000000000000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d33000000000100000003002386f26fc1000000000000000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d34000000000100000004002386f26fc1000000000000000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f676f65726c692f6e642d35000000000100000005002386f26fc1000000001d7e0000000af944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a68747470733a2f2f74696e6375626574682e6b6f6d707574696e672e6f72672f000000000100000006002386f26fc10000000021660000000a56d986deb3b5d14cb230d0f39247cc32416020b668747470733a2f2f68356c3435666b7a7a376f6333676d622e6f6e696f6e2f000000000100000007002386f26fc100000000000a000001d11821354870a09e3c4d2ed1a5c4b481e38e3d6ba168747470733a2f2f696e336e6f64652e636f6d0000000001c03e3500000000003be744c439cc9951feb98e36d776f408503c0c146a9fe37c30c142e82a634960 - -:: cache nodelist_2000_0xa93b57289070550c82edb1106e12bb37138948b8 0 - -:: cache nodelist_153_0xc2c05fbfe76ee7748ae5f5b61b57a46cc4061c32 1 -06c2c05fbfe76ee7748ae5f5b61b57a46cc4061c32000000000000000000000001170000004b930200722abd5f0000000000000001000000000000000000000000000000000000ffff1234567890123456789012345678901234567890687474703a2f2f6c6f63616c686f73743a383530300000000000 - -:: cache nodelist_246_0x039562872008f7a76674a6e7842804f0ad37cb13 1 -06039562872008f7a76674a6e7842804f0ad37cb1300000000007323630000000501000000020500000000000000000000000000000000000000000000000000001b250000e0c40d0080510100000000001b2500006ac30d0080510100000000001b25000026230e0080510100000000000000000100000000002386f26fc1000000000002000001dd45d45e6ff99e6c34a235d263965910298985fcfe68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d31000000000100000001002386f26fc1000000000002000001dd1fe2e9bf29aa1938859af64c413361227d04059a68747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d32000000000100000002002386f26fc1000000000002000001dd945f75c0408c0026a3cd204d36f5e47745182fd468747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d33000000000100000003002386f26fc1000000000002000001ddc513a534de5a9d3f413152c41b09bd8116237fc868747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d34000000000100000004002386f26fc1000000000002000001ddbcdf4e3e90cc7288b578329efd7bcc90655148d268747470733a2f2f696e332d76322e736c6f636b2e69742f6577632f6e642d3500000000016323730000000000822678d7e7ff274c3ee8c55199d2ce12c45637362c511f86fc948592d585be24 - -:: cache nodelist_17_0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9 0 - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: cache zksync_tokens_69f5 1 -000045544800000000001200000000000000000000000000000000000000000002007742544300000000083fad2b2e21ea1c96618cc76a42fb5a77c3f71c6f0001004441490000000000125e6d086f5ec079adff4fb3774cdf3e8d6a34f7e90003004241540000000000122c7e84980191210883d2df3167a3ab6a2cc15e010004004d4c545400000000125c55e2cf0a4243b9c7676e0ad8687c308959a15300 - -:: request http://localhost:3030 - [{"id":2,"jsonrpc":"2.0","method":"account_info","params":["0x3b98be46d348d45ddcd3343f7fdb21373e7f197c"]}] - -:: response account_info 0 http://localhost:3030 0 549 -[{ - "jsonrpc":"2.0", - "result":{ - "address":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c", - "id":8, - "depositing":{ - "balances":{ - - } - }, - "committed":{ - "balances":{ - "ETH":"999952780000000000" - }, - "nonce":2, - "pubKeyHash":"sync:9d9625572548e7fe4ba248ac60c0c7fdaca432cc" - }, - "verified":{ - "balances":{ - "ETH":"1990493664000000000" - }, - "nonce":0, - "pubKeyHash":"sync:0000000000000000000000000000000000000000" - } - }, - "id":2 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: request http://localhost:3030 - [{"id":3,"jsonrpc":"2.0","method":"get_tx_fee","params":["Withdraw","0xec8b8b4e05f647b36fa31d76273a7dc2860d0e73","ETH"]}] - -:: response get_tx_fee 0 http://localhost:3030 0 329 -[{ - "jsonrpc":"2.0", - "result":{ - "feeType":"Withdraw", - "gasTxAmount":"45000", - "gasPriceWei":"1000000000", - "gasFee":"45000000000000", - "zkpFee":"29128020447628", - "totalFee":"74100000000000" - }, - "id":3 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: request http://localhost:3030 - [{"id":4,"jsonrpc":"2.0","method":"tx_submit","params":[{"type":"Withdraw","accountId":8,"from":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","to":"0xec8b8b4e05f647b36fa31d76273a7dc2860d0e73","token":0,"amount":90493664000000000,"fee":74100000000000,"nonce":2,"signature":{"pubKey":"33624d532da9ec053a183287a59f0af93750fa98f4c6c43f1beec1381bf03d12","signature":"f0d1f59463c754c2251c7e7c37c939e67bf51a5287bbd6fdc6c882842135c793f97a7727faf5d9a9c4a378b66a24f0c04a72ada926a31c96e81709e34c2f3101"}},{"type":"EthereumSignature","signature":"0x06be65908613dc12a1ddaffadd9d674543b0ff75395ae744714c5b787fb398da18cfc2fa057e214e2163e6bf2a6f24b17f207c123157e5db382620b4e8bf225d1c"}]}] - -:: response tx_submit 0 http://localhost:3030 0 36 -[{ - "jsonrpc":"2.0", - "result":"sync-tx:3a2eabf1f9f6f1fdba6830c4479306151dc54814535cca9451ab45f6f133512f", - "id":4 -}] - - -:: cache zksync_ac3b98be46d348d45ddcd3343f7fdb21373e7f197c 1 -00000008 - -:: result -{"type":"Withdraw","accountId":8,"from":"0x3b98be46d348d45ddcd3343f7fdb21373e7f197c","to":"0xec8b8b4e05f647b36fa31d76273a7dc2860d0e73","token":0,"amount":90493664000000000,"fee":74100000000000,"nonce":2,"txHash":"sync-tx:3a2eabf1f9f6f1fdba6830c4479306151dc54814535cca9451ab45f6f133512f"} From 4495b39039905ed6b53a310cfd48001822d05cc6 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 14:20:01 +0200 Subject: [PATCH 193/221] fix wasm --- wasm/src/wasm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wasm/src/wasm.c b/wasm/src/wasm.c index 4e5dfd87a..86863831a 100644 --- a/wasm/src/wasm.c +++ b/wasm/src/wasm.c @@ -531,8 +531,8 @@ uint8_t* EMSCRIPTEN_KEEPALIVE ec_sign(bytes32_t pk, d_signature_type_t type, uin sha3_256_Init(&kctx); const char* PREFIX = "\x19" "Ethereum Signed Message:\n"; sha3_Update(&kctx, (uint8_t*) PREFIX, strlen(PREFIX)); - sha3_Update(&kctx, hash, sprintf((char*)hash,"%d", (int)ctx->message.len) ); - if (ctx->message.len) sha3_Update(&kctx, ctx->message.data, ctx->message.len); + sha3_Update(&kctx, hash, sprintf((char*)hash,"%d", len) ); + if (len) sha3_Update(&kctx, data, len); keccak_Final(&kctx, hash); error = ecdsa_sign_digest(&secp256k1, pk, hash, dst, dst + 64, NULL); break; From f668b4f6393be5ccd4f37ab330ce5bb1f30af2b5 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 15:48:34 +0200 Subject: [PATCH 194/221] fix documentation --- scripts/generator/generate.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/scripts/generator/generate.js b/scripts/generator/generate.js index 07ffec6ac..9ae19aef2 100755 --- a/scripts/generator/generate.js +++ b/scripts/generator/generate.js @@ -66,7 +66,7 @@ function scan(dir) { -function print_object(def, pad, useNum, doc) { +function print_object(def, pad, useNum, doc, pre) { let i = 1 for (const prop of Object.keys(def)) { let s = pad + (useNum ? ((i++) + '.') : '*') + ' **' + prop + '**' @@ -79,12 +79,26 @@ function print_object(def, pad, useNum, doc) { if (p.default) s += ' (default: `' + JSON.stringify(p.default) + '`)' if (p.enum) s += '\n' + pad + 'Possible Values are:\n\n' + Object.keys(p.enum).map(v => pad + ' - `' + v + '` : ' + p.enum[v]).join('\n') + '\n' if (p.alias) s += '\n' + pad + 'The data structure of ' + prop + ' is the same as ' + link(p.alias) + '. See Details there.' + if (p.cmd) asArray(p.cmd).forEach(_ => s += '\n' + pad + 'This option can also be used in its short-form in the comandline client `-' + _ + '` .') doc.push(s) if (typeof pt === 'object') { - rpc_doc.push('The ' + prop + ' object supports the following properties :\n' + pad) + doc.push('The ' + prop + ' object supports the following properties :\n' + pad) print_object(pt, pad + ' ', false, doc) } - if (p.example) rpc_doc.push('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) + if (rpc_doc === doc) { + if (p.example) doc.push('\n' + pad + ' *Example* : ' + prop + ': ' + JSON.stringify(p.example)) + } + else if (config_doc === doc) + asArray(p.example).forEach(ex => { + key = prop + doc.push(pad+'```sh') + if (typeof (ex) == 'object') + doc.push(pad+'> ' + cmdName + ' ' + Object.keys(ex).filter(_ => typeof (ex[_]) !== 'object').map(k => '--' + pre + key + '.' + k + '=' + ex[k]).join(' ') + ' ....\n') + else + doc.push(pad+[...asArray(p.cmd).map(_ => '-' + _), '--' + pre + key].map(_ => '> ' + cmdName + ' ' + _ + (ex === true ? '' : (_.startsWith('--') ? '=' : ' ') + ex) + ' ....').join('\n') + '\n') + doc.push(pad+'```\n') + }) + doc.push(pad + '\n') } } @@ -107,7 +121,7 @@ function handle_config(conf, pre, title, descr) { config_doc.push(s) if (typeof (c.type) === 'object') { config_doc.push('The ' + key + ' object supports the following properties :\n') - print_object(c.type, '', false, config_doc) + print_object(c.type, '', false, config_doc, key+".") } if (c.example !== undefined) { config_doc.push('\n*Example:*\n') From c13fa1386820c5b4ed10d74fae7c366cc2eb0539 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 31 May 2021 22:19:37 +0200 Subject: [PATCH 195/221] fix warning --- c/src/signer/multisig/multisig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/signer/multisig/multisig.c b/c/src/signer/multisig/multisig.c index e5a64fad1..d9af76aab 100644 --- a/c/src/signer/multisig/multisig.c +++ b/c/src/signer/multisig/multisig.c @@ -174,7 +174,7 @@ in3_ret_t get_tx_hash(in3_req_t* ctx, multisig_t* ms, tx_data_t* tx_data, bytes3 long_to_bytes(nonce, raw + 4 + 9 * 32 + 24); TRY(call(ctx, ms->address, bytes(raw, size), &rpc_result)) - if (rpc_result->len != 32) return req_set_error(ctx, "invalid getTransactionHash result!", IN3_EINVAL); + if (!rpc_result || rpc_result->len != 32) return req_set_error(ctx, "invalid getTransactionHash result!", IN3_EINVAL); memcpy(result, rpc_result->data, 32); return IN3_OK; } From ae9f465208f3cb35ae6b962f09a3599f59cc577d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 2 Jun 2021 09:16:46 +0200 Subject: [PATCH 196/221] added zksync_account --- c/src/cmd/in3/args.h | 1 + c/src/pay/zksync/CMakeLists.txt | 1 + c/src/pay/zksync/rpc.yml | 371 ++++++++++++++++++++++++++++++++ c/src/pay/zksync/zk_rest.c | 86 ++++++++ c/src/pay/zksync/zksync.c | 9 + c/src/pay/zksync/zksync.h | 3 + scripts/_in3.sh | 17 +- 7 files changed, 483 insertions(+), 5 deletions(-) create mode 100644 c/src/pay/zksync/zk_rest.c diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 534eb5ab3..3a11deac4 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -141,6 +141,7 @@ const char* aliases[] = { "bw", "bootWeights=true", "rc", "requestCount", "zks", "zksync.provider_url", + "zkr", "zksync.rest_api", "zka", "zksync.account", "zsk", "zksync.sync_key", "zkat", "zksync.signer_type", diff --git a/c/src/pay/zksync/CMakeLists.txt b/c/src/pay/zksync/CMakeLists.txt index b7a93ae26..414ef88d4 100644 --- a/c/src/pay/zksync/CMakeLists.txt +++ b/c/src/pay/zksync/CMakeLists.txt @@ -46,6 +46,7 @@ add_static_library( zk_deposit.c zk_musig.c zk_incentive.c + zk_rest.c DEPENDS eth_basic diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 1d8f38737..3eff5ec5d 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -28,6 +28,174 @@ types: descr: the transactionHash, which can be used to track the tx type: string + zk_tx: + accountId: + descr: the id of the sender account + type: uint64 + from: + descr: the address of the sender + type: address + to: + descr: the address of the receipient + type: address + token: + descr: the id of the token used + type: uint64 + amount: + descr: the amount sent + type: uint256 + fee: + descr: the fees paid + type: uint256 + nonce: + descr: the fees paid + type: uint64 + validFrom: + descr: timestamp set by the sender when the valid range starts + type: uint64 + validUntil: + descr: timestamp set by the sender when the valid range ends + type: uint64 + signature: + descr: the sync signature + type: + pubKey: + descr: the public key of the signer + type: bytes32 + signature: + descr: the signature + type: bytes + + zk_history: + tx_id: + descr: the transaction id based on the block-number and the index + type: string + hash: + descr: the transaction hash + type: string + eth_block: + descr: the blockNumber of a priority-operation like `Deposit` otherwise this is null + optional: true + type: uint64 + pq_id: + descr: the priority-operation id (for tx like `Deposit`) otherwise this is null + optional: true + type: uint64 + sucess: + descr: the result of the operation + type: bool + fail_reason: + descr: the error message if failed, otherwise null + type: string + optional: true + commited: + descr: true if the tx was received and verified by the zksync-server + type: bool + verified: + descr: true if the tx was received and verified by the zksync-server + type: bool + created_at: + descr: UTC-Time when the transaction was created + type: string + tx: + descr: the transaction data + type: + type: + descr: Type of the transaction. `Transfer`, `ChangePubKey` or `Withdraw` + type: string + from: + descr: The sender of the address + optional: true + type: address + to: + descr: The recipient of the address + optional: true + type: address + token: + descr: The token id + type: string + optional: true + amount: + descr: the amount sent + type: uint256 + optional: true + account: + descr: the account sent from + type: address + optional: true + accountId: + descr: the account id used + type: uint64 + optional: true + newPkHash: + descr: the new public Key Hash (only used if the type is CHangePubKey) + type: string + optional: true + validFrom: + descr: timestamp set by the sender when the valid range starts + type: uint64 + optional: true + validUntil: + descr: timestamp set by the sender when the valid range ends + type: uint64 + optional: true + signature: + optional: true + descr: the sync signature + type: + pubKey: + descr: the public key of the signer + type: bytes32 + signature: + descr: the signature + type: bytes + fee: + optional: true + descr: the fee payed + type: uint256 + feeToken: + optional: true + descr: the token the fee was payed + type: uint64 + nonce: + optional: true + descr: the nonce of the account + type: uint64 + priority_op: + descr: the description of a priority operation like `Deposit` + optional: true + type: + from: + descr: The sender of the address + type: address + to: + descr: The recipient of the address + type: address + token: + descr: The token id + type: string + amount: + descr: the amount sent + type: uint256 + ethAuthData: + descr: the 2fa euth authorition + optional: true + type: + type: + descr: the type which should be CREATE2, ECDSA + type: string + saltArg: + descr: the hash component (only if type=CREATE2) + type: bytes32 + optional: true + codeHash: + descr: the hash of the deployment-data (only if type=CREATE2) + type: bytes32 + optional: true + creatorAddress: + descr: the address of the the deploying contract (only if type=CREATE2) + type: address + optional: true zksync: descr: | @@ -71,6 +239,13 @@ zksync: default: https://api.zksync.io/jsrpc cmd: zks + rest_api: + descr: url of the zksync rest api (if not defined it will be choosen depending on the chain) + type: string + optional: true + example: https://rinkeby-api.zksync.io/api/v0.1/ + cmd: zkr + account: descr: the account to be used. if not specified, the first signer will be used. type: address @@ -298,6 +473,202 @@ zksync: failReason: null success: null + + zksync_tx_data: + descr: returns the full input data of a transaction. In order to use this, the `rest_api` needs to be set in the config. + params: + tx: + descr: the txHash of the send tx + type: bytes32 + result: + descr: the data and state of the requested tx. + type: + block_number: + descr: the blockNumber containing the tx or `null` if still pending + type: uint64 + optional: true + failReason: + descr: if executed and failed this will include an error message + type: string + optional: true + tx_type: + descr: Type of the transaction. `Transfer`, `ChangePubKey` or `Withdraw` + type: string + from: + descr: The sender of the address + type: address + to: + descr: The recipient of the address + type: address + token: + descr: The token id + type: uint64 + amount: + descr: the amount sent + type: uint256 + fee: + descr: the fee payed + type: uint256 + nonce: + descr: the nonce of the account + type: uint64 + created_at: + descr: the timestamp as UTC + type: string + tx: + descr: the tx input data + type: zk_tx + + example: + cmdParams: -x -zkr https://rinkeby-api.zksync.io/api/v0.1 + request: + - "0xc06ddc1c0914e8f9ca4d5bc98f609f7d758f6de2733fdcb8e3ec" + response: + tx_type: Transfer + from: '0x627d8e8c1a663cfea17432ec6dbbd3cc2c8a1f9a' + to: '0x03e2c10b74a260f46ab5cf881938c5888a6142df' + token: 1 + amount: '5000000' + fee: '2190' + block_number: 29588 + nonce: 20 + created_at: '2021-06-01T10:32:16.248564' + fail_reason: + tx: + to: '0x03e2c10b74a260f46ab5cf881938c5888a6142df' + fee: '2190' + from: '0x627d8e8c1a663cfea17432ec6dbbd3cc2c8a1f9a' + type: Transfer + nonce: 20 + token: 1 + amount: '5000000' + accountId: 161578 + signature: + pubKey: 91b533af2c430d7ad48db3ccc4ccb54befaff48307180c9a19a369099331d0a6 + signature: d17637db375a7a587474c8fee519fd7520f6ef98e1370e7a13d5de8176a6d0a22309e24a19dae50dad94ac9634ab3398427cf67abe8408e6c965c6b350b80c02 + validFrom: 0 + validUntil: 4294967295 + + + + zksync_account_history: + descr: returns the history of transaction for a given account. + params: + tx: + descr: the address of the account + type: address + ref: + descr: the reference or start. this could be a tx_id prefixed with `<` or `>`for newer or older than the specified tx or `pending` returning all pending tx. + type: string + optional: true + limit: + descr: the max number of entries to return + type: int + optional: true + result: + array: true + descr: the data and state of the requested tx. + type: zk_history + + example: + cmdParams: -x -zkr https://rinkeby-api.zksync.io/api/v0.1 + request: + - "0x9df215737e137acddd0ad99e32f9a6b980ea526d" + response: + - tx_id: '29411,1' + hash: sync-tx:e83b1b982b4d8a08a21f87717e85a268e3b3a5305bdf5efc465e7fd8f0ad5335 + eth_block: + pq_id: + tx: + to: '0xb7b2af693a2362c5c7575841ca6eb72ad2aed77f' + fee: '11060000000000' + from: '0x9df215737e137acddd0ad99e32f9a6b980ea526d' + type: Transfer + nonce: 1 + token: ETH + amount: '1000000000000000' + accountId: 161418 + signature: + pubKey: 74835ee6dd9009b67fd4e4aef4a6f63ee2a597ced5e59f33b019905d1df70d91 + signature: 407314ebce8ce0217b41a6cf992c7359645215c35afbdf7e18e76c957a14ed20135b7e8e5ca24fb132640141c0b3168b3939571e2363e41639e18b1637f26d02 + validFrom: 0 + validUntil: 4294967295 + success: true + fail_reason: + commited: true + verified: true + created_at: '2021-05-31T11:54:56.248569Z' + - tx_id: '29376,10' + hash: sync-tx:5f92999f7bbc5d84fe0d34ebe8b7a0c38f977caece844686d3007bc48e5944e0 + eth_block: + pq_id: + tx: + to: '0xc98fc74a085cd7ecd91d9e8d860a18ef6769d873' + fee: '10450000000000' + from: '0xb7b2af693a2362c5c7575841ca6eb72ad2aed77f' + type: Transfer + nonce: 1 + token: ETH + amount: '10000000000000000' + accountId: 161391 + signature: + pubKey: 06cce677912252a9eb87090b795e5bd84a079cb398dfec7f6a6645ee456dc721 + signature: ef83b1519a737107798aa5740998a515c406510b61f176fbbac6f703231968a563551f74f37bf96c2220fd18a68aca128a155b5083333a13cfbbd348c0a75003 + validFrom: 0 + validUntil: 4294967295 + success: true + fail_reason: + commited: true + verified: true + created_at: '2021-05-31T08:11:17.250144Z' + - tx_id: '29376,5' + hash: sync-tx:78550bbcaefdfd4cc4275bd1a0168dd73efb1953bb17a9689381fea6729c924e + eth_block: + pq_id: + tx: + fee: '37500000000000' + type: ChangePubKey + nonce: 0 + account: '0xb7b2af693a2362c5c7575841ca6eb72ad2aed77f' + feeToken: 0 + accountId: 161391 + newPkHash: sync:1ae5a093f285ddd23b54bea2780ef4e9a4e348ea + signature: + pubKey: 06cce677912252a9eb87090b795e5bd84a079cb398dfec7f6a6645ee456dc721 + signature: 27f42a850de4dcc6527fea0a9baa5991dabf3c2ce30dae5a6112f03cf614da03bdc2ef7ac107337d17f9e4047e5b18b3e4c46acb6af41f8cfbb2fce43247d500 + validFrom: 0 + validUntil: 4294967295 + ethAuthData: + type: CREATE2 + saltArg: '0xd32a7ec6157d2433c9ae7f4fdc35dfac9bba6f92831d1ca20b09d04d039d8dd7' + codeHash: '0x96657bf6bdcbffce06518530907d2d729e4659ad3bc7b5cc1f5c5567d964272c' + creatorAddress: '0xaa8c54c65c14f132804f0809bdbef19970673709' + ethSignature: + success: true + fail_reason: + commited: true + verified: true + created_at: '2021-05-31T08:09:11.249472Z' + - tx_id: '29376,0' + hash: '0xc63566212c1569a0e64b255a07320483ed8476cd36b54aa37d3bd6f93b70f7f8' + eth_block: 8680840 + pq_id: 57181 + tx: + type: Deposit + account_id: 161391 + priority_op: + to: '0xb7b2af693a2362c5c7575841ca6eb72ad2aed77f' + from: '0x9d646b325787c6d7d612eb37915ca3023eea4dac' + token: ETH + amount: '500000000000000000' + success: true + fail_reason: + commited: true + verified: true + created_at: '2021-05-31T08:07:31.237817Z' + + + zksync_set_key: descr: | sets the signerkey based on the current pk or as configured in the config. diff --git a/c/src/pay/zksync/zk_rest.c b/c/src/pay/zksync/zk_rest.c new file mode 100644 index 000000000..269237d54 --- /dev/null +++ b/c/src/pay/zksync/zk_rest.c @@ -0,0 +1,86 @@ +#include "../../core/client/keys.h" +#include "../../core/client/plugin.h" +#include "../../core/client/request_internal.h" +#include "../../core/util/debug.h" +#include "../../core/util/mem.h" +#include "../../third-party/zkcrypto/lib.h" +#include "zk_helper.h" +#include "zksync.h" +#include +#include +#include +#include + +#define CHECK_REST_API(ctx,conf) if (!conf->rest_api) return req_set_error(ctx->req,"No zksync Rest-Api set in config",IN3_ECONFIG); + + +in3_ret_t zksync_tx_data(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { + CHECK_REST_API(ctx,conf) + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) + CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) + CHECK_PARAM_LEN(ctx->req, ctx->params, 0, 32) + + d_token_t* res = NULL; + in3_req_t* req = NULL; + sb_t sb = {0}; + sb_add_chars(&sb, "\"GET\",\""); + sb_add_escaped_chars(&sb, conf->rest_api); + sb_add_rawbytes(&sb,"/transactions_all/0x",d_to_bytes(ctx->params+1),32); + sb_add_chars(&sb, "\""); + + TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) + + char* resp = d_create_json(req->response_context,res); + in3_rpc_handle_with_string(ctx,resp); + _free(resp); + return IN3_OK; +} + + +in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { + CHECK_REST_API(ctx,conf) + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) + CHECK_PARAM_ADDRESS(ctx->req, ctx->params, 0) + + d_token_t* ref_tx = d_get_at(ctx->params,1); + d_token_t* limit = d_get_at(ctx->params,2); + if (!limit && d_type(ref_tx)==T_INTEGER) { + limit = ref_tx; + ref_tx = NULL; + } + if (d_type(ref_tx)==T_NULL) ref_tx = NULL; + if (ref_tx && d_type(ref_tx)!=T_STRING) return req_set_error(ctx->req,"The 2nd argument in account History (base tx) must be a string starting with < or > and the transactionId",IN3_ECONFIG); + if (limit && d_type(limit)!=T_INTEGER) return req_set_error(ctx->req,"The 3rd argument in account History (limit) must be a integer!",IN3_ECONFIG); + + d_token_t* res = NULL; + in3_req_t* req = NULL; + sb_t sb = {0}; + sb_add_chars(&sb, "\"GET\",\""); + sb_add_escaped_chars(&sb, conf->rest_api); + sb_add_rawbytes(&sb,"/account/0x",d_to_bytes(ctx->params+1),20); + sb_add_chars(&sb, "/history/"); + if (!ref_tx) { + sb_add_chars(&sb, "0/"); + sb_add_int(&sb, limit ? (int64_t)d_long(limit) : 100); + } + else if (strcmp(d_string(ref_tx),"pending")==0) + sb_add_chars(&sb, "newer_than"); + else if (ref_tx->data[0]=='<' || ref_tx->data[0]=='>') { + sb_add_chars(&sb, ref_tx->data[0]=='<' ? "older_than?tx_id=" : "newer_than?tx_id="); + sb_add_chars(&sb, d_string(ref_tx)); + sb_add_chars(&sb, "&limit="); + sb_add_int(&sb, limit ? (int64_t)d_long(limit) : 100); + } + else { + _free(sb.data); + return req_set_error(ctx->req,"Invalid base_tx it must a tx_id with <,> or pending",IN3_ECONFIG); + } + sb_add_chars(&sb, "\""); + + TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) + + char* resp = d_create_json(req->response_context,res); + in3_rpc_handle_with_string(ctx,resp); + _free(resp); + return IN3_OK; +} diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index f63a11e9e..8e06fa92b 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -162,6 +162,9 @@ static in3_ret_t zksync_rpc(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { TRY_RPC("verify", in3_rpc_handle_with_int(ctx, conf->musig_pub_keys.data ? zkcrypto_verify_signatures(d_to_bytes(ctx->params + 1), conf->musig_pub_keys, d_to_bytes(ctx->params + 2)) : zkcrypto_verify_musig(d_to_bytes(ctx->params + 1), d_to_bytes(ctx->params + 2)))) + TRY_RPC("tx_data", zksync_tx_data(conf, ctx)) + TRY_RPC("account_history", zksync_account_history(conf, ctx)) + // prepare fallback to send to zksync-server str_range_t p = d_to_json(ctx->params); @@ -201,6 +204,7 @@ static in3_ret_t config_free(zksync_config_t* conf, bool free_conf) { } _free(conf->musig_urls); } + if (conf->rest_api) _free(conf->rest_api); if (conf->provider_url) _free(conf->provider_url); if (conf->main_contract) _free(conf->main_contract); if (conf->account) _free(conf->account); @@ -247,6 +251,11 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { if (conf->provider_url) _free(conf->provider_url); conf->provider_url = _strdupn(provider, -1); } + const char* rest_api = d_get_string(ctx->token, CONFIG_KEY("rest_api")); + if (rest_api) { + if (conf->rest_api) _free(conf->rest_api); + conf->rest_api = _strdupn(rest_api, -1); + } const char* pvm = d_get_string(ctx->token, CONFIG_KEY("verify_proof_method")); if (pvm) { if (conf->proof_verify_method) _free(conf->proof_verify_method); diff --git a/c/src/pay/zksync/zksync.h b/c/src/pay/zksync/zksync.h index 1bf10f837..aaf040f33 100644 --- a/c/src/pay/zksync/zksync.h +++ b/c/src/pay/zksync/zksync.h @@ -106,6 +106,7 @@ struct pay_criteria; /** internal configuration-object */ typedef struct zksync_config { char* provider_url; /**< url of the zksync-server */ + char* rest_api; /**< url of the zksync-rest-api */ uint8_t* account; /**< address of the account */ uint8_t* main_contract; /**< address of the main zksync contract*/ uint8_t* gov_contract; /**< address of the government contract */ @@ -182,6 +183,8 @@ in3_ret_t zksync_check_payment(zksync_config_t* conf, in3_pay_followup in3_ret_t zksync_add_payload(in3_pay_payload_ctx_t* ctx); in3_ret_t update_nodelist_from_cache(in3_req_t* req, unsigned int nodelen); in3_ret_t handle_zksync(void* conf, in3_plugin_act_t action, void* arg); +in3_ret_t zksync_tx_data(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); +in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); #ifdef __cplusplus } #endif diff --git a/scripts/_in3.sh b/scripts/_in3.sh index 2e9bff2b1..c60441985 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -67,7 +67,7 @@ subcmds=( 'in3_fromWei: converts a given uint (also as hex) with a wei-value into a specified unit ' 'in3_toWei: converts the given value into wei ' 'keccak: Returns Keccak-256 (not the standardized SHA3-256) of the given data' - 'net_version: the Network Version (currently 1)' + 'net_version: Returns the current network id' 'sha256: Returns sha-256 of the given data ' 'web3_clientVersion: Returns the underlying client version' 'web3_sha3: Returns Keccak-256 (not the standardized SHA3-256) of the given data ' @@ -98,14 +98,15 @@ args=( '--finality=[the number in percent needed in order reach finality (% of signature of the validators)]:finality:()' '-f[the number in percent needed in order reach finality (% of signature of the validators)]:finality:()' '--includeCode[if true, the request should include the codes of all accounts]' +'--debug[if true, debug messages will be written to stderr]' '--maxAttempts=[max number of attempts in case a response is rejected]:maxAttempts:()' '-a[max number of attempts in case a response is rejected]:maxAttempts:()' '--keepIn3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' '-kin3[if true, requests sent to the input sream of the comandline util will be send theor responses in the...]' '--stats[if true, requests sent will be used for stats]' '--useBinary[if true the client will use binary format]' -'--experimental[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' -'-x[iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...]' +'--experimental[if true the client allows to use use experimental features, otherwise a exception is thrown if those...]' +'-x[if true the client allows to use use experimental features, otherwise a exception is thrown if those...]' '--timeout=[specifies the number of milliseconds before the request times out]:timeout:()' '--proof=[if true the nodes should send a proof of the response]:proof:(none standard full)' '-p[if true the nodes should send a proof of the response]:proof:(none standard full)' @@ -135,6 +136,8 @@ args=( '--nodes.nodeList.props=[used to identify the capabilities of the node (defaults to 0xFFFF)]:props:()' '--zksync.provider_url=[url of the zksync-server (if not defined it will be choosen depending on the chain)]:provider_url:()' '-zks[url of the zksync-server (if not defined it will be choosen depending on the chain)]:provider_url:()' +'--zksync.rest_api=[url of the zksync rest api (if not defined it will be choosen depending on the chain)]:rest_api:()' +'-zkr[url of the zksync rest api (if not defined it will be choosen depending on the chain)]:rest_api:()' '--zksync.account=[the account to be used]:account:()' '-zka[the account to be used]:account:()' '--zksync.sync_key=[the seed used to generate the sync_key]:sync_key:()' @@ -149,6 +152,10 @@ args=( '--zksync.create2.creator=[The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )]:creator:()' '--zksync.create2.saltarg=[a salt-argument, which will be added to the pubkeyhash and create the create2-salt]:saltarg:()' '--zksync.create2.codehash=[the hash of the actual deploy-tx including the constructor-arguments]:codehash:()' +'--zksync.verify_proof_method=[rpc-method, which will be used to verify the incomming proof before cosigning]:verify_proof_method:()' +'-zvpm[rpc-method, which will be used to verify the incomming proof before cosigning]:verify_proof_method:()' +'--zksync.create_proof_method=[rpc-method, which will be used to create the proof needed for cosigning]:create_proof_method:()' +'-zcpm[rpc-method, which will be used to create the proof needed for cosigning]:create_proof_method:()' '--key=[the client key to sign requests]:key:()' '-k[the client key to sign requests]:key:()' '--pk=[registers raw private keys as signers for transactions]:pk:()' @@ -219,8 +226,8 @@ args=( '-nl[a coma seperated list of urls (or address:url) to be used as fixed nodelist]:nodelist:()' '--bootnodes=[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' '-bn[a coma seperated list of urls (or address:url) to be used as boot nodes]:bootnodes:()' -'--onlysign[only sign, don't send the raw Transaction]' -'-os[only sign, don't send the raw Transaction]' +'--onlysign[only sign, do not send the raw Transaction]' +'-os[only sign, do not send the raw Transaction]' '--noproof[alias for --proof=none]' '-np[alias for --proof=none]' '--nostats[alias for --stats=false, which will mark all requests as not counting in the stats]' From 1a42e80e65adc1fdcd8de4123b49e95720218184 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 2 Jun 2021 09:19:08 +0200 Subject: [PATCH 197/221] updated zksync-features --- c/src/cmd/in3/args.h | 12 +++++++++--- scripts/_in3.sh | 2 ++ scripts/build_rpc.sh | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/c/src/cmd/in3/args.h b/c/src/cmd/in3/args.h index 3a11deac4..428acdba8 100644 --- a/c/src/cmd/in3/args.h +++ b/c/src/cmd/in3/args.h @@ -2,17 +2,18 @@ #include -const char* bool_props[] = {"includeCode", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; +const char* bool_props[] = {"includeCode", "debug", "keepIn3", "stats", "useBinary", "experimental", "autoUpdateList", "bootWeights", "useHttp", "nodes.needsUpdate", "clearCache", "eth", "wait", "json", "hex", "debug", "quiet", "human", "test-request", "test-health-request", "response.in", "response.out", "onlysign", "noproof", "nostats", "version", "help", NULL}; const char* help_args = "\ --chainId -c the chainId or the name of a known chain\n\ --finality -f the number in percent needed in order reach finality (% of signature of the validators)\n\ --includeCode if true, the request should include the codes of all accounts\n\ +--debug if true, debug messages will be written to stderr\n\ --maxAttempts -a max number of attempts in case a response is rejected\n\ --keepIn3 -kin3 if true, requests sent to the input sream of the comandline util will be send theor responses in the...\n\ --stats if true, requests sent will be used for stats\n\ --useBinary if true the client will use binary format\n\ ---experimental -x iif true the client allows to use use experimental features, otherwise a exception is thrown if thos...\n\ +--experimental -x if true the client allows to use use experimental features, otherwise a exception is thrown if those...\n\ --timeout specifies the number of milliseconds before the request times out\n\ --proof -p if true the nodes should send a proof of the response\n\ --replaceLatestBlock -l if specified, the blocknumber *latest* will be replaced by blockNumber- specified value\n\ @@ -40,6 +41,7 @@ const char* help_args = "\ --nodes.nodeList.props used to identify the capabilities of the node (defaults to 0xFFFF)\n\ --zksync configuration for zksync-api ( only available if build with `-DZKSYNC=true`, which is on per defaul...\n\ --zksync.provider_url -zks url of the zksync-server (if not defined it will be choosen depending on the chain)\n\ +--zksync.rest_api -zkr url of the zksync rest api (if not defined it will be choosen depending on the chain)\n\ --zksync.account -zka the account to be used\n\ --zksync.sync_key -zsk the seed used to generate the sync_key\n\ --zksync.main_contract address of the main contract- If not specified it will be taken from the server\n\ @@ -50,6 +52,8 @@ const char* help_args = "\ --zksync.create2.creator The address of contract or EOA deploying the contract ( for example the GnosisSafeFactory )\n\ --zksync.create2.saltarg a salt-argument, which will be added to the pubkeyhash and create the create2-salt\n\ --zksync.create2.codehash the hash of the actual deploy-tx including the constructor-arguments\n\ +--zksync.verify_proof_method -zvpm rpc-method, which will be used to verify the incomming proof before cosigning\n\ +--zksync.create_proof_method -zcpm rpc-method, which will be used to create the proof needed for cosigning\n\ --key -k the client key to sign requests\n\ --pk -pk registers raw private keys as signers for transactions\n\ --btc configure the Bitcoin verification\n\ @@ -87,7 +91,7 @@ const char* help_args = "\ --file.out -fo records a request and writes the reproducable data in a file (including all cache-data, timestamps \n\ --nodelist -nl a coma seperated list of urls (or address:url) to be used as fixed nodelist\n\ --bootnodes -bn a coma seperated list of urls (or address:url) to be used as boot nodes\n\ ---onlysign -os only sign, don't send the raw Transaction\n\ +--onlysign -os only sign, do not send the raw Transaction\n\ --noproof -np alias for --proof=none\n\ --nostats -ns alias for --stats=false, which will mark all requests as not counting in the stats\n\ --version -v displays the version\n\ @@ -148,6 +152,8 @@ const char* aliases[] = { "zms", "zksync.musig_pub_keys", "zmu", "zksync.musig_urls", "zc2", "zksync.create2", + "zvpm", "zksync.verify_proof_method", + "zcpm", "zksync.create_proof_method", "k", "key", "pk", "pk", "ccache", "clearCache=true", diff --git a/scripts/_in3.sh b/scripts/_in3.sh index c60441985..e41437e03 100755 --- a/scripts/_in3.sh +++ b/scripts/_in3.sh @@ -72,6 +72,7 @@ subcmds=( 'web3_clientVersion: Returns the underlying client version' 'web3_sha3: Returns Keccak-256 (not the standardized SHA3-256) of the given data ' 'zksync_account_address: returns the address of the account used' + 'zksync_account_history: returns the history of transaction for a given account ' 'zksync_account_info: returns account_info from the server
' 'zksync_aggregate_pubkey: calculate the public key based on multiple public keys signing together using schnorr musig signatur... ' 'zksync_contract_address: returns the contract address' @@ -87,6 +88,7 @@ subcmds=( 'zksync_sync_key: returns private key used for signing zksync-transactions' 'zksync_tokens: returns the list of all available tokens' 'zksync_transfer: sends a zksync-transaction and returns data including the transactionHash ' + 'zksync_tx_data: returns the full input data of a transaction ' 'zksync_tx_info: returns the state or receipt of the the zksync-tx ' 'zksync_verify: returns 0 or 1 depending on the successfull verification of the signature ' 'zksync_withdraw: withdraws the amount to the given `ethAddress` for the given token ' diff --git a/scripts/build_rpc.sh b/scripts/build_rpc.sh index e9cc26c47..e28aa2b9a 100755 --- a/scripts/build_rpc.sh +++ b/scripts/build_rpc.sh @@ -1,3 +1,3 @@ #!/bin/sh -generator/generate.js --src=../c/src --doc=../../../doc/docs --zsh=_in3.template --arg=../c/src/cmd/in3/args.h \ No newline at end of file +generator/generate.js --src=../c/src --doc=../../in3-doc/docs --zsh=_in3.template --arg=../c/src/cmd/in3/args.h From 680162efde8144d575404ef5f8ea2127d1bb834f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BCchler?= Date: Thu, 3 Jun 2021 10:41:10 +0200 Subject: [PATCH 198/221] added ETH_FULL check to in3_signTx --- c/src/api/eth1/rpc_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/api/eth1/rpc_api.c b/c/src/api/eth1/rpc_api.c index a8267fcaf..7ca45855f 100644 --- a/c/src/api/eth1/rpc_api.c +++ b/c/src/api/eth1/rpc_api.c @@ -539,7 +539,7 @@ static in3_ret_t in3_signTx(in3_rpc_handle_ctx_t* ctx) { bytes_t* from_b = NULL; bytes_t* data = NULL; if (strcmp(ctx->method, "eth_signTransaction") == 0 || d_type(tx_data) == T_OBJECT) { -#if defined(ETH_BASIC) +#if defined(ETH_BASIC) || defined(ETH_FULL) TRY(eth_prepare_unsigned_tx(tx_data, ctx->req, &tx_raw)) from_b = d_get_bytes(tx_data, K_FROM); data = &tx_raw; From 80761f3bd2367841ddec671c78f689d971638516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BCchler?= Date: Thu, 3 Jun 2021 17:38:58 +0200 Subject: [PATCH 199/221] fixed private2public --- wasm/src/in3_util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 467aa4034..729574fa7 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -175,7 +175,7 @@ function private2address(pk) { function private2public(pk) { if (!pk) return pk pk = toUint8Array(pk) - return toChecksumAddress(call_buffer('private_to_public', 20, pk, pk.byteLength)) // alias for 'in3_pk2public' + return call_buffer('private_to_public', 64, pk, pk.byteLength) // alias for 'in3_pk2public' } function checkAddressChecksum(ad, chain = 0) { From 5c487e51dacc123007797d6058ce2771b60ce340 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Thu, 3 Jun 2021 18:33:47 +0200 Subject: [PATCH 200/221] fixed commited --- c/src/core/client/request.c | 4 ++++ c/src/pay/zksync/rpc.yml | 4 ++-- c/src/pay/zksync/zk_musig.c | 4 ++-- c/src/pay/zksync/zk_rest.c | 1 + wasm/src/wasm.c | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/c/src/core/client/request.c b/c/src/core/client/request.c index 5c60cc68e..a9eac38d5 100644 --- a/c/src/core/client/request.c +++ b/c/src/core/client/request.c @@ -79,6 +79,7 @@ in3_req_t* req_new(in3_t* client, const char* req_data) { if (req_data != NULL) { ctx->request_context = parse_json(req_data); if (!ctx->request_context) { + in3_log_error("Invalid json-request: %s\n",req_data); req_set_error(ctx, "Error parsing the JSON-request!", IN3_EINVAL); return ctx; } @@ -412,6 +413,8 @@ in3_ret_t req_require_signature(in3_req_t* ctx, d_signature_type_t type, bytes_t return IN3_OK; } + in3_log_debug("requesting signature type=%d from account %x\n",type,from.len>2? bytes_to_int(from.data,4):0); + // first try internal plugins for signing, before we create an context. if (in3_plugin_is_registered(ctx->client, PLGN_ACT_SIGN)) { in3_sign_ctx_t sc = {.account = from, .req = ctx, .message = raw_data, .signature = bytes(NULL, 0), .type = type}; @@ -424,6 +427,7 @@ in3_ret_t req_require_signature(in3_req_t* ctx, d_signature_type_t type, bytes_t else if (r != IN3_EIGNORE && r != IN3_OK) return r; } + in3_log_debug("nobody picked up the signature, sending req now \n"); // get the signature from required const char* method = type == SIGN_EC_HASH ? "sign_ec_hash" : (type == SIGN_EC_PREFIX ? "sign_ec_prefix" : "sign_ec_raw"); diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 3eff5ec5d..10bd19484 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -387,7 +387,7 @@ zksync: address: descr: the address of the account type: address - commited: + committed: descr: the state of the zksync operator after executing transactions successfully, but not not verified on L1 yet. type: balances: @@ -554,7 +554,7 @@ zksync: zksync_account_history: descr: returns the history of transaction for a given account. params: - tx: + account: descr: the address of the account type: address ref: diff --git a/c/src/pay/zksync/zk_musig.c b/c/src/pay/zksync/zk_musig.c index 6dd855fdf..2f498cce8 100644 --- a/c/src/pay/zksync/zk_musig.c +++ b/c/src/pay/zksync/zk_musig.c @@ -332,8 +332,8 @@ in3_ret_t zksync_musig_sign(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { TRY_SIG(zkcrypto_compute_aggregated_pubkey(s->pub_keys, res)) TRY_SIG(zkcrypto_signer_receive_signature_shares(s->signer, s->signature_shares, res + 32)) cleanup_session(s, conf); - if (!zkcrypto_verify_signatures(message, conf->musig_pub_keys, bytes(res, 96))) - return req_set_error(ctx->req, "invalid signature", IN3_EINVAL); +// if (!zkcrypto_verify_signatures(message, conf->musig_pub_keys, bytes(res, 96))) +// return req_set_error(ctx->req, "invalid signature", IN3_EINVAL); return in3_rpc_handle_with_bytes(ctx, bytes(res, 96)); } diff --git a/c/src/pay/zksync/zk_rest.c b/c/src/pay/zksync/zk_rest.c index 269237d54..1fd3cdfe8 100644 --- a/c/src/pay/zksync/zk_rest.c +++ b/c/src/pay/zksync/zk_rest.c @@ -52,6 +52,7 @@ in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ct if (ref_tx && d_type(ref_tx)!=T_STRING) return req_set_error(ctx->req,"The 2nd argument in account History (base tx) must be a string starting with < or > and the transactionId",IN3_ECONFIG); if (limit && d_type(limit)!=T_INTEGER) return req_set_error(ctx->req,"The 3rd argument in account History (limit) must be a integer!",IN3_ECONFIG); + if (limit && !d_int(limit)) limit = NULL; d_token_t* res = NULL; in3_req_t* req = NULL; sb_t sb = {0}; diff --git a/wasm/src/wasm.c b/wasm/src/wasm.c index 86863831a..773296ae2 100644 --- a/wasm/src/wasm.c +++ b/wasm/src/wasm.c @@ -266,7 +266,7 @@ char* EMSCRIPTEN_KEEPALIVE ctx_execute(in3_req_t* ctx) { sb_add_chars(sb, ",\"wait\":"); sb_add_int(sb, (uint64_t) request->wait); sb_add_chars(sb, ",\"payload\":"); - sb_add_chars(sb, request->payload); + sb_add_chars(sb, (request->payload && strlen(request->payload))?request->payload:"null"); sb_add_chars(sb, ",\"method\":\""); sb_add_chars(sb, request->method); sb_add_chars(sb, "\",\"urls\":["); From 0415085b1c479af6689be82c16fae4fdee46130d Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 16:09:32 +0200 Subject: [PATCH 201/221] fixed format --- c/src/cmd/http-server/http_server.c | 14 ++-- c/src/pay/zksync/zk_rest.c | 119 ++++++++++++++-------------- c/src/pay/zksync/zksync.c | 1 - c/src/pay/zksync/zksync.h | 4 +- 4 files changed, 69 insertions(+), 69 deletions(-) diff --git a/c/src/cmd/http-server/http_server.c b/c/src/cmd/http-server/http_server.c index 9f17e89a4..671393550 100644 --- a/c/src/cmd/http-server/http_server.c +++ b/c/src/cmd/http-server/http_server.c @@ -100,12 +100,8 @@ typedef struct queue { req_t* r; } queue_t; -queue_t * q_head = NULL, *q_tail = NULL; -static void error_response(char* message, int error_code) { - char* payload = alloca(strlen(message) + 100); - sprintf(payload, "{\"id\":1,\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"%s\",\"code\":%i}}", message, error_code); - printf("HTTP/1.1 200\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: %lu\r\n\r\n%s\r\n", strlen(payload), payload); -} +queue_t *q_head = NULL, *q_tail = NULL; + static void queue_add(req_t* r) { pthread_mutex_lock(&queue_mutex); queue_t* q = _malloc(sizeof(queue_t)); @@ -148,6 +144,12 @@ static void* thread_run(void* p) { static int clients[MAX_CON]; #endif +static void error_response(char* message, int error_code) { + char* payload = alloca(strlen(message) + 100); + sprintf(payload, "{\"id\":1,\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"%s\",\"code\":%i}}", message, error_code); + printf("HTTP/1.1 200\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: %lu\r\n\r\n%s\r\n", strlen(payload), payload); +} + //client connection void* respond(void* arg) { req_t* r = arg; diff --git a/c/src/pay/zksync/zk_rest.c b/c/src/pay/zksync/zk_rest.c index 269237d54..09845ab15 100644 --- a/c/src/pay/zksync/zk_rest.c +++ b/c/src/pay/zksync/zk_rest.c @@ -11,76 +11,75 @@ #include #include -#define CHECK_REST_API(ctx,conf) if (!conf->rest_api) return req_set_error(ctx->req,"No zksync Rest-Api set in config",IN3_ECONFIG); - +#define CHECK_REST_API(ctx, conf) \ + if (!conf->rest_api) return req_set_error(ctx->req, "No zksync Rest-Api set in config", IN3_ECONFIG); in3_ret_t zksync_tx_data(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { - CHECK_REST_API(ctx,conf) - CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) - CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) - CHECK_PARAM_LEN(ctx->req, ctx->params, 0, 32) + CHECK_REST_API(ctx, conf) + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) + CHECK_PARAM_TYPE(ctx->req, ctx->params, 0, T_BYTES) + CHECK_PARAM_LEN(ctx->req, ctx->params, 0, 32) - d_token_t* res = NULL; - in3_req_t* req = NULL; - sb_t sb = {0}; - sb_add_chars(&sb, "\"GET\",\""); - sb_add_escaped_chars(&sb, conf->rest_api); - sb_add_rawbytes(&sb,"/transactions_all/0x",d_to_bytes(ctx->params+1),32); - sb_add_chars(&sb, "\""); + d_token_t* res = NULL; + in3_req_t* req = NULL; + sb_t sb = {0}; + sb_add_chars(&sb, "\"GET\",\""); + sb_add_escaped_chars(&sb, conf->rest_api); + sb_add_rawbytes(&sb, "/transactions_all/0x", d_to_bytes(ctx->params + 1), 32); + sb_add_chars(&sb, "\""); - TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) + TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) - char* resp = d_create_json(req->response_context,res); - in3_rpc_handle_with_string(ctx,resp); - _free(resp); - return IN3_OK; + char* resp = d_create_json(req->response_context, res); + in3_rpc_handle_with_string(ctx, resp); + _free(resp); + return IN3_OK; } - in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { - CHECK_REST_API(ctx,conf) - CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) - CHECK_PARAM_ADDRESS(ctx->req, ctx->params, 0) + CHECK_REST_API(ctx, conf) + CHECK_PARAMS_LEN(ctx->req, ctx->params, 1) + CHECK_PARAM_ADDRESS(ctx->req, ctx->params, 0) - d_token_t* ref_tx = d_get_at(ctx->params,1); - d_token_t* limit = d_get_at(ctx->params,2); - if (!limit && d_type(ref_tx)==T_INTEGER) { - limit = ref_tx; - ref_tx = NULL; - } - if (d_type(ref_tx)==T_NULL) ref_tx = NULL; - if (ref_tx && d_type(ref_tx)!=T_STRING) return req_set_error(ctx->req,"The 2nd argument in account History (base tx) must be a string starting with < or > and the transactionId",IN3_ECONFIG); - if (limit && d_type(limit)!=T_INTEGER) return req_set_error(ctx->req,"The 3rd argument in account History (limit) must be a integer!",IN3_ECONFIG); + d_token_t* ref_tx = d_get_at(ctx->params, 1); + d_token_t* limit = d_get_at(ctx->params, 2); + if (!limit && d_type(ref_tx) == T_INTEGER) { + limit = ref_tx; + ref_tx = NULL; + } + if (d_type(ref_tx) == T_NULL) ref_tx = NULL; + if (ref_tx && d_type(ref_tx) != T_STRING) return req_set_error(ctx->req, "The 2nd argument in account History (base tx) must be a string starting with < or > and the transactionId", IN3_ECONFIG); + if (limit && d_type(limit) != T_INTEGER) return req_set_error(ctx->req, "The 3rd argument in account History (limit) must be a integer!", IN3_ECONFIG); - d_token_t* res = NULL; - in3_req_t* req = NULL; - sb_t sb = {0}; - sb_add_chars(&sb, "\"GET\",\""); - sb_add_escaped_chars(&sb, conf->rest_api); - sb_add_rawbytes(&sb,"/account/0x",d_to_bytes(ctx->params+1),20); - sb_add_chars(&sb, "/history/"); - if (!ref_tx) { - sb_add_chars(&sb, "0/"); - sb_add_int(&sb, limit ? (int64_t)d_long(limit) : 100); - } - else if (strcmp(d_string(ref_tx),"pending")==0) - sb_add_chars(&sb, "newer_than"); - else if (ref_tx->data[0]=='<' || ref_tx->data[0]=='>') { - sb_add_chars(&sb, ref_tx->data[0]=='<' ? "older_than?tx_id=" : "newer_than?tx_id="); - sb_add_chars(&sb, d_string(ref_tx)); - sb_add_chars(&sb, "&limit="); - sb_add_int(&sb, limit ? (int64_t)d_long(limit) : 100); - } - else { - _free(sb.data); - return req_set_error(ctx->req,"Invalid base_tx it must a tx_id with <,> or pending",IN3_ECONFIG); - } - sb_add_chars(&sb, "\""); + d_token_t* res = NULL; + in3_req_t* req = NULL; + sb_t sb = {0}; + sb_add_chars(&sb, "\"GET\",\""); + sb_add_escaped_chars(&sb, conf->rest_api); + sb_add_rawbytes(&sb, "/account/0x", d_to_bytes(ctx->params + 1), 20); + sb_add_chars(&sb, "/history/"); + if (!ref_tx) { + sb_add_chars(&sb, "0/"); + sb_add_int(&sb, limit ? (int64_t) d_long(limit) : 100); + } + else if (strcmp(d_string(ref_tx), "pending") == 0) + sb_add_chars(&sb, "newer_than"); + else if (ref_tx->data[0] == '<' || ref_tx->data[0] == '>') { + sb_add_chars(&sb, ref_tx->data[0] == '<' ? "older_than?tx_id=" : "newer_than?tx_id="); + sb_add_chars(&sb, d_string(ref_tx)); + sb_add_chars(&sb, "&limit="); + sb_add_int(&sb, limit ? (int64_t) d_long(limit) : 100); + } + else { + _free(sb.data); + return req_set_error(ctx->req, "Invalid base_tx it must a tx_id with <,> or pending", IN3_ECONFIG); + } + sb_add_chars(&sb, "\""); - TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) + TRY_FINAL(req_send_sub_request(ctx->req, "in3_http", sb.data, NULL, &res, &req), _free(sb.data)) - char* resp = d_create_json(req->response_context,res); - in3_rpc_handle_with_string(ctx,resp); - _free(resp); - return IN3_OK; + char* resp = d_create_json(req->response_context, res); + in3_rpc_handle_with_string(ctx, resp); + _free(resp); + return IN3_OK; } diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index 8e06fa92b..cc921fb44 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -165,7 +165,6 @@ static in3_ret_t zksync_rpc(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { TRY_RPC("tx_data", zksync_tx_data(conf, ctx)) TRY_RPC("account_history", zksync_account_history(conf, ctx)) - // prepare fallback to send to zksync-server str_range_t p = d_to_json(ctx->params); char* param_string = alloca(p.len - 1); diff --git a/c/src/pay/zksync/zksync.h b/c/src/pay/zksync/zksync.h index aaf040f33..b93ec3616 100644 --- a/c/src/pay/zksync/zksync.h +++ b/c/src/pay/zksync/zksync.h @@ -183,8 +183,8 @@ in3_ret_t zksync_check_payment(zksync_config_t* conf, in3_pay_followup in3_ret_t zksync_add_payload(in3_pay_payload_ctx_t* ctx); in3_ret_t update_nodelist_from_cache(in3_req_t* req, unsigned int nodelen); in3_ret_t handle_zksync(void* conf, in3_plugin_act_t action, void* arg); -in3_ret_t zksync_tx_data(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); -in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); +in3_ret_t zksync_tx_data(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); +in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx); #ifdef __cplusplus } #endif From 91a4d46e91a67f4d828f0a1869f1301f57b0b60c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 17:19:32 +0200 Subject: [PATCH 202/221] added parse-function --- java/src/in3/utils/JSON.java | 8 ++++++++ java/src/in3_jni.c | 28 ++++++++++++++++++++++++++++ java/src/in3_jni.h | 8 ++++++++ 3 files changed, 44 insertions(+) diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 003eb9e26..36fd5e490 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -348,4 +348,12 @@ public T put(String key, T value) { } }; } + + + /** parses a String to a json-object. If the json represents + * - a object : JSON is returned + * - a Array : a Array is returned + * - other types the wrapped primative typed (Boolean, Integer, Long or String) will be returned. + */ + public static native Object parse(String json) throws Exception; } diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index e91614415..e977ccc68 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -161,6 +161,9 @@ JNIEXPORT void JNICALL Java_in3_IN3_initcache(JNIEnv* env, jobject ob) { in3_cache_init(c, in3_nodeselect_def_data(c)); } + + + /* * Class: in3_IN3 * Method: sendinternal @@ -665,3 +668,28 @@ JNIEXPORT void JNICALL Java_in3_Loader_libInit(JNIEnv* env, jclass c) { UNUSED_VAR(c); in3_init(); } + + +/* + * Class: in3_utils_JSON + * Method: parse + * Signature: (Ljava/lang/String;)Lin3/JSON; + */ +JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv* env, jclass cl, jstring jdata) { + jobject ob = NULL; + const char* data = (*env)->GetStringUTFChars(env, jdata, 0); + const json_ctx_t* ctx = parse_json(data); + (*env)->ReleaseStringUTFChars(env, jdata, data); + if (ctx==NULL) { + char* error = _malloc(strlen(jdata)+50); + sprintf(error,"Error parsing the json-data : '%s'",data); + (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), error); + _free(error); + } + else { + ob = toObject( env, ctx->result); + json_free(ctx); + } + + return ob; +} diff --git a/java/src/in3_jni.h b/java/src/in3_jni.h index ca584c53c..ff95107fe 100644 --- a/java/src/in3_jni.h +++ b/java/src/in3_jni.h @@ -171,6 +171,14 @@ JNIEXPORT jstring JNICALL Java_in3_eth1_TransactionRequest_abiEncode(JNIEnv*, jc */ JNIEXPORT jobject JNICALL Java_in3_eth1_TransactionRequest_abiDecode(JNIEnv*, jclass, jstring, jstring); +/* + * Class: in3_utils_JSON + * Method: parse + * Signature: (Ljava/lang/String;)Lin3/JSON; + */ +JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv*, jclass, jstring); + + /* * Class: in3_eth1_SimpleWallet * Method: getAddressFromKey From 4fa18ecac7bd6e1575aae0adcd398311cecb5ab6 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 17:31:04 +0200 Subject: [PATCH 203/221] fix warnings --- java/src/in3_jni.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index e977ccc68..0163dffe3 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -676,12 +676,13 @@ JNIEXPORT void JNICALL Java_in3_Loader_libInit(JNIEnv* env, jclass c) { * Signature: (Ljava/lang/String;)Lin3/JSON; */ JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv* env, jclass cl, jstring jdata) { + UNUSED_VAR(cl); jobject ob = NULL; const char* data = (*env)->GetStringUTFChars(env, jdata, 0); - const json_ctx_t* ctx = parse_json(data); + json_ctx_t* ctx = parse_json(data); (*env)->ReleaseStringUTFChars(env, jdata, data); if (ctx==NULL) { - char* error = _malloc(strlen(jdata)+50); + char* error = _malloc(strlen(data)+50); sprintf(error,"Error parsing the json-data : '%s'",data); (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), error); _free(error); From 386f07c1dde95a6ca55637b31a3f7428e6ce693c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 18:38:48 +0200 Subject: [PATCH 204/221] handle NULL-Ptr in java --- java/src/in3_jni.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index 0163dffe3..7ba6cf009 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -67,7 +67,7 @@ static void* get_java_obj_ptr(in3_t* c) { for (in3_plugin_t* p = c->plugins; p; p = p->next) { if (p->acts & PLGN_ACT_CACHE_GET) { in3_storage_handler_t* st = p->data; - return st->cptr; + return st ? st->cptr : NULL; } } return NULL; @@ -553,6 +553,7 @@ JNIEXPORT jstring JNICALL Java_in3_eth1_SimpleWallet_decodeKeystore(JNIEnv* env, in3_ret_t jsign(in3_sign_ctx_t* sc) { in3_req_t* ctx = (in3_req_t*) sc->req; void* jp = get_java_obj_ptr(ctx->client); + if (jp==NULL) return IN3_EIGNORE; jclass cls = (*jni)->GetObjectClass(jni, jp); jmethodID mid = (*jni)->GetMethodID(jni, cls, "getSigner", "()Lin3/utils/Signer;"); jobject signer = (*jni)->CallObjectMethod(jni, jp, mid); From 7fa59743520bd4c92059af64d29942133f274417 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 20:23:02 +0200 Subject: [PATCH 205/221] add debug and NULL check --- java/src/in3_jni.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index 7ba6cf009..f135de972 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -64,9 +64,12 @@ typedef struct in3_storage_handler { } in3_storage_handler_t; static void* get_java_obj_ptr(in3_t* c) { + in3_log_debug(":: get_java_obj_ptr %p \n",c); + if (!c) return NULL; for (in3_plugin_t* p = c->plugins; p; p = p->next) { if (p->acts & PLGN_ACT_CACHE_GET) { in3_storage_handler_t* st = p->data; + in3_log_debug(":: found CACHE %p \n",st); return st ? st->cptr : NULL; } } @@ -553,6 +556,7 @@ JNIEXPORT jstring JNICALL Java_in3_eth1_SimpleWallet_decodeKeystore(JNIEnv* env, in3_ret_t jsign(in3_sign_ctx_t* sc) { in3_req_t* ctx = (in3_req_t*) sc->req; void* jp = get_java_obj_ptr(ctx->client); + in3_log_debug(":: jsign for %p === %p\n",ctx->client,jp); if (jp==NULL) return IN3_EIGNORE; jclass cls = (*jni)->GetObjectClass(jni, jp); jmethodID mid = (*jni)->GetMethodID(jni, cls, "getSigner", "()Lin3/utils/Signer;"); @@ -643,13 +647,14 @@ JNIEXPORT jlong JNICALL Java_in3_IN3_init(JNIEnv* env, jobject ob, jlong jchain) in3_init(); in3_t* in3 = in3_for_chain(jchain); void* p = (*env)->NewGlobalRef(env, ob); +// in3_log_set_level(LOG_TRACE); +// in3_log_set_quiet(false); + in3_log_debug("New Global ref for %p === %p\n",ob,p); in3_set_storage_handler(in3, storage_get_item, storage_set_item, storage_clear, p); in3_plugin_register(in3, PLGN_ACT_TRANSPORT, Java_in3_IN3_transport, NULL, true); in3_plugin_register(in3, PLGN_ACT_SIGN, jsign_fn, p, false); jni = env; // turn to debug - // in3_log_set_level(LOG_TRACE); - // in3_log_set_quiet(false); return (jlong)(size_t) in3; } From 4ba7af7fcf13c71090003c05f06e51c360d8df5c Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 20:57:47 +0200 Subject: [PATCH 206/221] fix signer-check --- c/src/signer/pk-signer/signer.c | 5 +++- java/src/in3/utils/JSON.java | 1 - java/src/in3_jni.c | 45 +++++++++++++++------------------ java/src/in3_jni.h | 1 - 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index 163be482d..074772887 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -74,9 +74,12 @@ static bool add_key(in3_t* c, bytes32_t pk) { address_t address; get_address(pk, address); in3_sign_account_ctx_t ctx = {0}; + in3_req_t r = {0}; + ctx.req = &r; + r.client = c; for (in3_plugin_t* p = c->plugins; p; p = p->next) { - if (p->acts & (PLGN_ACT_SIGN_ACCOUNT | PLGN_ACT_SIGN) && p->action_fn(p->data, PLGN_ACT_SIGN_ACCOUNT, &ctx) == IN3_OK && ctx.accounts_len) { + if ((p->acts & PLGN_ACT_SIGN_ACCOUNT) && (p->acts & PLGN_ACT_SIGN) && p->action_fn(p->data, PLGN_ACT_SIGN_ACCOUNT, &ctx) == IN3_OK && ctx.accounts_len) { bool is_same_address = memcmp(ctx.accounts, address, 20) == 0; _free(ctx.accounts); if (is_same_address) return false; diff --git a/java/src/in3/utils/JSON.java b/java/src/in3/utils/JSON.java index 36fd5e490..cfc050c29 100644 --- a/java/src/in3/utils/JSON.java +++ b/java/src/in3/utils/JSON.java @@ -349,7 +349,6 @@ public T put(String key, T value) { }; } - /** parses a String to a json-object. If the json represents * - a object : JSON is returned * - a Array : a Array is returned diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index f135de972..80d475f43 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -64,12 +64,12 @@ typedef struct in3_storage_handler { } in3_storage_handler_t; static void* get_java_obj_ptr(in3_t* c) { - in3_log_debug(":: get_java_obj_ptr %p \n",c); + in3_log_debug(":: get_java_obj_ptr %p \n", c); if (!c) return NULL; for (in3_plugin_t* p = c->plugins; p; p = p->next) { if (p->acts & PLGN_ACT_CACHE_GET) { in3_storage_handler_t* st = p->data; - in3_log_debug(":: found CACHE %p \n",st); + in3_log_debug(":: found CACHE %p \n", st); return st ? st->cptr : NULL; } } @@ -164,9 +164,6 @@ JNIEXPORT void JNICALL Java_in3_IN3_initcache(JNIEnv* env, jobject ob) { in3_cache_init(c, in3_nodeselect_def_data(c)); } - - - /* * Class: in3_IN3 * Method: sendinternal @@ -554,13 +551,14 @@ JNIEXPORT jstring JNICALL Java_in3_eth1_SimpleWallet_decodeKeystore(JNIEnv* env, //in3_ret_t jsign(void* pk, d_signature_type_t type, bytes_t message, bytes_t account, uint8_t* dst) { in3_ret_t jsign(in3_sign_ctx_t* sc) { - in3_req_t* ctx = (in3_req_t*) sc->req; - void* jp = get_java_obj_ptr(ctx->client); - in3_log_debug(":: jsign for %p === %p\n",ctx->client,jp); - if (jp==NULL) return IN3_EIGNORE; - jclass cls = (*jni)->GetObjectClass(jni, jp); - jmethodID mid = (*jni)->GetMethodID(jni, cls, "getSigner", "()Lin3/utils/Signer;"); - jobject signer = (*jni)->CallObjectMethod(jni, jp, mid); + in3_req_t* ctx = (in3_req_t*) sc->req; + if (ctx == NULL) return IN3_EIGNORE; + void* jp = get_java_obj_ptr(ctx->client); + in3_log_debug(":: jsign for %p === %p\n", ctx->client, jp); + if (jp == NULL) return IN3_EIGNORE; + jclass cls = (*jni)->GetObjectClass(jni, jp); + jmethodID mid = (*jni)->GetMethodID(jni, cls, "getSigner", "()Lin3/utils/Signer;"); + jobject signer = (*jni)->CallObjectMethod(jni, jp, mid); if (!signer) return -1; @@ -647,9 +645,9 @@ JNIEXPORT jlong JNICALL Java_in3_IN3_init(JNIEnv* env, jobject ob, jlong jchain) in3_init(); in3_t* in3 = in3_for_chain(jchain); void* p = (*env)->NewGlobalRef(env, ob); -// in3_log_set_level(LOG_TRACE); -// in3_log_set_quiet(false); - in3_log_debug("New Global ref for %p === %p\n",ob,p); + // in3_log_set_level(LOG_TRACE); + // in3_log_set_quiet(false); + in3_log_debug("New Global ref for %p === %p\n", ob, p); in3_set_storage_handler(in3, storage_get_item, storage_set_item, storage_clear, p); in3_plugin_register(in3, PLGN_ACT_TRANSPORT, Java_in3_IN3_transport, NULL, true); in3_plugin_register(in3, PLGN_ACT_SIGN, jsign_fn, p, false); @@ -675,7 +673,6 @@ JNIEXPORT void JNICALL Java_in3_Loader_libInit(JNIEnv* env, jclass c) { in3_init(); } - /* * Class: in3_utils_JSON * Method: parse @@ -683,19 +680,19 @@ JNIEXPORT void JNICALL Java_in3_Loader_libInit(JNIEnv* env, jclass c) { */ JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv* env, jclass cl, jstring jdata) { UNUSED_VAR(cl); - jobject ob = NULL; - const char* data = (*env)->GetStringUTFChars(env, jdata, 0); - json_ctx_t* ctx = parse_json(data); + jobject ob = NULL; + const char* data = (*env)->GetStringUTFChars(env, jdata, 0); + json_ctx_t* ctx = parse_json(data); (*env)->ReleaseStringUTFChars(env, jdata, data); - if (ctx==NULL) { - char* error = _malloc(strlen(data)+50); - sprintf(error,"Error parsing the json-data : '%s'",data); + if (ctx == NULL) { + char* error = _malloc(strlen(data) + 50); + sprintf(error, "Error parsing the json-data : '%s'", data); (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), error); _free(error); } else { - ob = toObject( env, ctx->result); - json_free(ctx); + ob = toObject(env, ctx->result); + json_free(ctx); } return ob; diff --git a/java/src/in3_jni.h b/java/src/in3_jni.h index ff95107fe..e7f84561d 100644 --- a/java/src/in3_jni.h +++ b/java/src/in3_jni.h @@ -178,7 +178,6 @@ JNIEXPORT jobject JNICALL Java_in3_eth1_TransactionRequest_abiDecode(JNIEnv*, jc */ JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv*, jclass, jstring); - /* * Class: in3_eth1_SimpleWallet * Method: getAddressFromKey From 9899664fcbef8db36f4982721732946372392827 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Fri, 4 Jun 2021 22:12:37 +0200 Subject: [PATCH 207/221] fixed signer --- java/src/in3_jni.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index 80d475f43..8cb8c4349 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -560,7 +560,7 @@ in3_ret_t jsign(in3_sign_ctx_t* sc) { jmethodID mid = (*jni)->GetMethodID(jni, cls, "getSigner", "()Lin3/utils/Signer;"); jobject signer = (*jni)->CallObjectMethod(jni, jp, mid); - if (!signer) return -1; + if (!signer) return IN3_EIGNORE; char *data = alloca(sc->message.len * 2 + 3), address[43]; data[0] = address[0] = '0'; @@ -574,7 +574,7 @@ in3_ret_t jsign(in3_sign_ctx_t* sc) { mid = (*jni)->GetMethodID(jni, cls, "sign", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); jstring jsignature = (*jni)->CallObjectMethod(jni, signer, mid, jdata, jaddress); - if (!jsignature) return -2; + if (!jsignature) return IN3_EIGNORE; const char* signature = (*jni)->GetStringUTFChars(jni, jsignature, 0); int l = (strlen(signature) + 1) / 2; if (l && signature[0] == '0' && signature[1] == 'x') l--; From 657f9d41db00d7e52f30a68780d9ea5d5bd091fa Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 7 Jun 2021 11:57:11 +0200 Subject: [PATCH 208/221] flush after response --- c/src/cmd/in3/req_exec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/src/cmd/in3/req_exec.c b/c/src/cmd/in3/req_exec.c index a7d44de4a..9294f8f19 100644 --- a/c/src/cmd/in3/req_exec.c +++ b/c/src/cmd/in3/req_exec.c @@ -67,6 +67,7 @@ static void execute(in3_t* c, FILE* f) { else recorder_print(0, "{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":{\"code\":%i,\"message\":\"%s\"}}\n", id, ctx->verification_state, ctx->error == NULL ? "Unknown error" : ctx->error); } + fflush(stdout); req_free(ctx); first = 0; sb->len = 0; From 46a3b3fc0076fecec218abb3f6fdfbcc0984e82b Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 7 Jun 2021 16:19:51 +0200 Subject: [PATCH 209/221] change to runtime-exception --- java/src/in3_jni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/in3_jni.c b/java/src/in3_jni.c index 8cb8c4349..495f96e0b 100644 --- a/java/src/in3_jni.c +++ b/java/src/in3_jni.c @@ -687,7 +687,7 @@ JNIEXPORT jobject JNICALL Java_in3_utils_JSON_parse(JNIEnv* env, jclass cl, jstr if (ctx == NULL) { char* error = _malloc(strlen(data) + 50); sprintf(error, "Error parsing the json-data : '%s'", data); - (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/Exception"), error); + (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), error); _free(error); } else { From 1f02a8d0b301f6d758648a8ea00c1ff2d9f06777 Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 17:49:36 +0200 Subject: [PATCH 210/221] extended UInt64 max to 21 to support huge numbers --- c/src/core/util/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/core/util/data.c b/c/src/core/util/data.c index 49ed3dbec..2bb60a447 100644 --- a/c/src/core/util/data.c +++ b/c/src/core/util/data.c @@ -372,7 +372,7 @@ NONULL int parse_number(json_ctx_t* jp, d_token_t* item) { uint64_t value = 0; // the resulting value (if it is a integer) jp->c--; // we also need to include hte previous character! - for (int i = 0; i < 20; i++) { // we are not accepting more than 20 characters, since a uint64 can hold up to 18446744073709552000 (which has 20 digits) + for (int i = 0; i < 21; i++) { // we are not accepting more than 20 characters, since a uint64 can hold up to 18446744073709552000 (which has 20 digits) if (jp->c[i] >= '0' && jp->c[i] <= '9') // as long as this is a digit value = value * 10 + (jp->c[i] - '0'); // we handle it and add it to the value. else { From 90cd829de16ada229219d3b0631e286cdc007c29 Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 17:50:01 +0200 Subject: [PATCH 211/221] fixed typos and added optional --- c/src/pay/zksync/rpc.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 10bd19484..7dfb506b6 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -81,7 +81,7 @@ types: descr: the priority-operation id (for tx like `Deposit`) otherwise this is null optional: true type: uint64 - sucess: + success: descr: the result of the operation type: bool fail_reason: @@ -410,6 +410,7 @@ zksync: id: descr: the assigned id of the account, which will be used when encoding it into the rollup. type: uint64 + optional: true verified: descr: the state after the rollup was verified in L1. type: From 956279cdb58ec7a706b5b58036539ffe1315ad53 Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 17:50:43 +0200 Subject: [PATCH 212/221] added null check to optional parameter in history --- c/src/pay/zksync/zk_rest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/src/pay/zksync/zk_rest.c b/c/src/pay/zksync/zk_rest.c index 1ba36ca6b..3378b9d0c 100644 --- a/c/src/pay/zksync/zk_rest.c +++ b/c/src/pay/zksync/zk_rest.c @@ -48,6 +48,7 @@ in3_ret_t zksync_account_history(zksync_config_t* conf, in3_rpc_handle_ctx_t* ct ref_tx = NULL; } if (d_type(ref_tx) == T_NULL) ref_tx = NULL; + if (d_type(limit) == T_NULL) limit = NULL; if (ref_tx && d_type(ref_tx) != T_STRING) return req_set_error(ctx->req, "The 2nd argument in account History (base tx) must be a string starting with < or > and the transactionId", IN3_ECONFIG); if (limit && d_type(limit) != T_INTEGER) return req_set_error(ctx->req, "The 3rd argument in account History (limit) must be a integer!", IN3_ECONFIG); From 2c67e1236c2feb5c6525876f68d9ebbe7e857b09 Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 17:51:07 +0200 Subject: [PATCH 213/221] fixed optional address parameter in account info --- c/src/pay/zksync/zksync.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index cc921fb44..be4320e94 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -172,7 +172,7 @@ static in3_ret_t zksync_rpc(zksync_config_t* conf, in3_rpc_handle_ctx_t* ctx) { param_string[p.len - 2] = 0; if (strcmp(ctx->method, "account_info") == 0) { - if (*param_string == 0) { + if (*param_string == 0 || strcmp(param_string, "null") == 0) { TRY(zksync_get_account(conf, ctx->req, NULL)) param_string = alloca(45); set_quoted_address(param_string, conf->account); @@ -376,4 +376,4 @@ in3_ret_t in3_register_zksync(in3_t* c) { return in3_plugin_register(c, PLGN_ACT_RPC_HANDLE | PLGN_ACT_INIT | PLGN_ACT_TERM | PLGN_ACT_CONFIG_GET | PLGN_ACT_CONFIG_SET | PLGN_ACT_ADD_PAYLOAD | PLGN_ACT_PAY_FOLLOWUP, handle_zksync, conf, false); -} \ No newline at end of file +} From 06a41cc6722a00e56c3ac2eb397c7b12a9402c2c Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 17:54:11 +0200 Subject: [PATCH 214/221] change success to optional --- c/src/pay/zksync/rpc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 7dfb506b6..f05ce969d 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -84,6 +84,7 @@ types: success: descr: the result of the operation type: bool + optional: true fail_reason: descr: the error message if failed, otherwise null type: string @@ -460,6 +461,7 @@ zksync: success: descr: if executed, this property marks the success of the tx. type: bool + optional: true failReason: descr: if executed and failed this will include an error message type: string From ea83f0b74c41aa106bf449a620a554d0fff0453d Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 18:05:25 +0200 Subject: [PATCH 215/221] added ethOpInfo return type --- c/src/pay/zksync/rpc.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index f05ce969d..6275c20c3 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -801,6 +801,26 @@ zksync: opId: descr: the opId of a layer-operstion (like depositing) type: uint64 + result: + descr: state of the PriorityOperation + type: + block: + descr: the block + type: + committed: + descr: state of the operation + type: bool + verified: + descr: if the opteration id has been included in the rollup block + type: bool + blockNumber: + descr: the blocknumber of the block that included the operation + type: uint64 + optional: true + optional: true + executed: + descr: if the operation was executed + type: bool zksync_get_token_price: descr: returns current token-price From a34dc6d257fa43388ba46895cb9d6b59e81a0b4d Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 18:07:57 +0200 Subject: [PATCH 216/221] added example to EthOpInfo --- c/src/pay/zksync/rpc.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 6275c20c3..2f42eb94f 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -821,6 +821,16 @@ zksync: executed: descr: if the operation was executed type: bool + example: + cmdParams: -x + request: + - 1 + response: + block: + committed: true + blockNumber: 4 + verified: true + executed: true zksync_get_token_price: descr: returns current token-price From 7dead44e986bf11f41a57be726fd0dcb4cae1b4b Mon Sep 17 00:00:00 2001 From: jbentke Date: Thu, 10 Jun 2021 18:15:49 +0200 Subject: [PATCH 217/221] made proof methods in the config optional --- c/src/pay/zksync/rpc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/src/pay/zksync/rpc.yml b/c/src/pay/zksync/rpc.yml index 2f42eb94f..5df6ed25f 100644 --- a/c/src/pay/zksync/rpc.yml +++ b/c/src/pay/zksync/rpc.yml @@ -308,11 +308,13 @@ zksync: descr: rpc-method, which will be used to verify the incomming proof before cosigning. type: string cmd: zvpm + optional: true create_proof_method: descr: rpc-method, which will be used to create the proof needed for cosigning. type: string cmd: zcpm + optional: true # rpc zksync_contract_address: From 22366e04c4276a7f3fbbc467438fa856bbb070b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BCchler?= Date: Fri, 11 Jun 2021 11:13:15 +0200 Subject: [PATCH 218/221] fixexs for JS --- c/src/verifier/btc/rpc.yml | 12 +++--------- wasm/src/in3_util.js | 5 ++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/c/src/verifier/btc/rpc.yml b/c/src/verifier/btc/rpc.yml index f97f894de..74dd4cb02 100644 --- a/c/src/verifier/btc/rpc.yml +++ b/c/src/verifier/btc/rpc.yml @@ -562,8 +562,8 @@ btc: cmdParams: -x -c btc -f 8 request: - 'f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf' - - true - - '000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220' + # - true + # - '000000000000000000103b2395f6cd94221b10d02eb9be5850303c0534307220' response: in_active_chain: true txid: f3c06e17b04ef748ce6604ad68e5b9f68ca96914b57c2118a1bb9a09a194ddaf @@ -671,10 +671,6 @@ btc: getdifficulty: descr: Returns the proof-of-work difficulty as a multiple of the minimum difficulty. - params: - blocknumber: - type: uint64 - descr: 'Can be the number of a certain block to get its difficulty. To get the difficulty of the latest block use `latest`, `earliest`, `pending` or leave `params` empty (Hint: Latest block always means `actual latest block` minus `in3.finality`)' in3Params: finality: descr: defines the amount of finality headers @@ -687,7 +683,7 @@ btc: type: bool result: - type: uint256 + type: double descr: | - `blocknumber` is a certain number: the difficulty of this block - `blocknumber` is `latest`, `earliest`, `pending` or empty: the difficulty of the latest block (`actual latest block` minus `in3.finality`) @@ -733,8 +729,6 @@ btc: in3Params: finality: 8 cmdParams: -x -c btc -f 8 - request: - - 631910 response: 15138043247082.88 in3: proof: diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 729574fa7..7c963c4e7 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -347,10 +347,9 @@ function toNumber(val) { case 'string': return parseInt(val) case 'undefined': - case 'null': - return 0 + return undefined default: - if (!val) return 0 + if (!val) return val if (val.readBigInt64BE) //nodejs Buffer return val.length == 0 ? 0 : parseInt(toMinHex(val)) else if (val.redIMul) From f2a1a901beee0845a290499e92a091ed8ba5395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BCchler?= Date: Fri, 11 Jun 2021 12:39:27 +0200 Subject: [PATCH 219/221] updated toNumber test --- wasm/test/testUtil.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wasm/test/testUtil.js b/wasm/test/testUtil.js index 47254579d..41a317b10 100644 --- a/wasm/test/testUtil.js +++ b/wasm/test/testUtil.js @@ -163,8 +163,8 @@ describe('Util-Tests', () => { assert.equal(0, IN3.util.toNumber(false)) assert.equal(65535, IN3.util.toNumber(65535n)) assert.equal(65535, IN3.util.toNumber("65535")) - assert.equal(0, IN3.util.toNumber(undefined)) - assert.equal(0, IN3.util.toNumber(null)) + assert.equal(undefined, IN3.util.toNumber(undefined)) + assert.equal(null, IN3.util.toNumber(null)) assert.equal(97, IN3.util.toNumber(Buffer.from('a', 'utf8'))) assert.equal(255, IN3.util.toNumber("0xff")) assert.Throw(() => IN3.util.toNumber({})) From 28eae7a47d546378411f03950794fd5c977eb037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BCchler?= Date: Mon, 14 Jun 2021 09:53:15 +0200 Subject: [PATCH 220/221] added additional flags for eth-rpc-calls --- c/src/verifier/eth1/basic/rpc.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/c/src/verifier/eth1/basic/rpc.yml b/c/src/verifier/eth1/basic/rpc.yml index ea006fdde..0e7efd251 100644 --- a/c/src/verifier/eth1/basic/rpc.yml +++ b/c/src/verifier/eth1/basic/rpc.yml @@ -385,6 +385,7 @@ eth: proof: alias: eth_getUncleCountByBlockNumber result: + optional: true descr: the number of transactions in the block type: int @@ -397,6 +398,7 @@ eth: proof: alias: eth_getUncleCountByBlockNumber result: + optional: true descr: the number of transactions in the block type: int @@ -409,6 +411,7 @@ eth: proof: alias: eth_getUncleCountByBlockNumber result: + optional: true descr: the number of uncles type: int @@ -429,6 +432,7 @@ eth: - `finalityBlocks`: a array of blockHeaders which were mined after the requested block. The number of blocks depends on the request-property `finality`. If this is not specified, this property will not be defined. - `uncles`: a array of blockheaders of the uncles of the block. This is only needed if the number of uncles are requested. result: + optional: true descr: the number of uncles type: int @@ -445,6 +449,7 @@ eth: descr: the transactionIndex type: int result: + optional: true descr: the transactiondata or `null` if it does not exist type: transactiondata proof: @@ -497,6 +502,7 @@ eth: descr: the transactionIndex type: int result: + optional: true descr: the transactiondata or `null` if it does not exist type: transactiondata proof: @@ -546,6 +552,7 @@ eth: descr: the transactionHash of the transaction. type: bytes32 result: + optional: true descr: the transactiondata or `null` if it does not exist type: transactiondata From 68237ed14469f697e99e2d23f2e1456e25b3a325 Mon Sep 17 00:00:00 2001 From: jbentke Date: Mon, 14 Jun 2021 10:57:54 +0200 Subject: [PATCH 221/221] fixed a bug where musig urls where not set properl --- c/src/pay/zksync/zksync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index be4320e94..300086e0d 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -304,7 +304,7 @@ static in3_ret_t config_set(zksync_config_t* conf, in3_configure_ctx_t* ctx) { conf->musig_urls = _calloc(d_len(urls), sizeof(char*)); for (int i = 0; i < d_len(urls); i++) { char* s = d_get_string_at(urls, i); - if (s) conf->musig_urls[i] = _strdupn(s, -1); + if (s && strlen(s)) conf->musig_urls[i] = _strdupn(s, -1); } } }