From 635af5eadcdc6ce9991f543d89b5bb18f1e8ce44 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Mon, 5 Oct 2020 15:35:13 +0200 Subject: [PATCH 1/5] add output for logs --- c/test/vm_runner.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/test/vm_runner.c b/c/test/vm_runner.c index 49cf89188..00c957740 100644 --- a/c/test/vm_runner.c +++ b/c/test/vm_runner.c @@ -209,6 +209,7 @@ int main(int argc, char* argv[]) { in3_log_set_level(LOG_DEBUG); in3_log_set_prefix(""); + in3_log_set_quiet(false); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-t") == 0) From d6bed5b75bafd19efcbc897ed0febc741c4307d0 Mon Sep 17 00:00:00 2001 From: leonardocardoso Date: Mon, 5 Oct 2020 18:03:06 +0200 Subject: [PATCH 2/5] Fix deployment script for dotnet --- dotnet/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dotnet/ci.yml b/dotnet/ci.yml index 133dcb319..248953e81 100644 --- a/dotnet/ci.yml +++ b/dotnet/ci.yml @@ -94,8 +94,9 @@ release_nuget: - dotnet_macos script: - cd dotnet - - dotnet pack -c Release -p:version=${CI_COMMIT_TAG} - - dotnet nuget push In3/bin/Release/Blockchains.In3.${CI_COMMIT_TAG}.nupkg -k {NUGET_GALLERY_API_KEY} -s https://api.nuget.org/v3/index.json + - export NUGET_VERSION=$(echo "$CI_COMMIT_TAG" | cut -c 2-) + - dotnet pack -c Release -p:version=${NUGET_VERSION} + - dotnet nuget push In3/bin/Release/Blockchains.In3.${NUGET_VERSION}.nupkg -k {NUGET_GALLERY_API_KEY} -s https://api.nuget.org/v3/index.json artifacts: paths: - - dotnet/In3/bin/Release/Blockchains.In3.${CI_COMMIT_TAG}.nupkg + - dotnet/In3/bin/Release/Blockchains.In3.${NUGET_VERSION}.nupkg From e055f16716288a941b92fbf4e1a2e201bcffe307 Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Tue, 6 Oct 2020 09:16:37 +0200 Subject: [PATCH 3/5] rename to execLocal --- wasm/src/in3.js | 2 +- wasm/src/index.d.ts | 2 +- wasm/src/modules/eth.d.ts | 6 ++++++ wasm/src/modules/eth.js | 7 ++++++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/wasm/src/in3.js b/wasm/src/in3.js index ad62cc0e2..a7529caa9 100644 --- a/wasm/src/in3.js +++ b/wasm/src/in3.js @@ -334,7 +334,7 @@ class IN3 { return res.result } - sendSyncRPC(method, params = []) { + execLocal(method, params = []) { this._ensure_ptr_sync(); if (this.needsSetConfig) this.setConfig() const r = in3w.ccall('in3_create_request_ctx', 'number', ['number', 'string'], [this.ptr, JSON.stringify({ method, params })]); diff --git a/wasm/src/index.d.ts b/wasm/src/index.d.ts index 0881f29c1..873bd8187 100644 --- a/wasm/src/index.d.ts +++ b/wasm/src/index.d.ts @@ -456,7 +456,7 @@ export default class IN3Generic { * * @param method the method to call. */ - public sendSyncRPC(method: string, params?: any[]): any; + public execLocal(method: string, params?: any[]): any; /** * disposes the Client. This must be called in order to free allocated memory! diff --git a/wasm/src/modules/eth.d.ts b/wasm/src/modules/eth.d.ts index ef49849de..d41bb81fc 100644 --- a/wasm/src/modules/eth.d.ts +++ b/wasm/src/modules/eth.d.ts @@ -397,6 +397,12 @@ export interface EthAPI { * Returns the number of transactions sent from an address. (as number) */ getTransactionCount(address: Address, block?: BlockType): Promise; + + /** + * returns the public addresses accounts + */ + getAccounts(): Promise + /** * Returns the receipt of a transaction by transaction hash. * Note That the receipt is available even for pending transactions. diff --git a/wasm/src/modules/eth.js b/wasm/src/modules/eth.js index 2abcb5d37..ea5a7d191 100644 --- a/wasm/src/modules/eth.js +++ b/wasm/src/modules/eth.js @@ -37,7 +37,7 @@ class EthAPI { * Returns the number of most recent block. () */ toWei(val, unit = 'eth') { - return this.client.sendSyncRPC('in3_toWei', [val, unit]) + return this.client.execLocal('in3_toWei', [val, unit]) } /** @@ -306,6 +306,11 @@ class EthAPI { return this.send('eth_syncing') } + getAccounts() { + return this.send('eth_accounts') + } + + /** * Creates new message call transaction or a contract creation for signed transactions. From 888e794b14a7ca5b79cc93307658a6802b169cfc Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Oct 2020 11:45:15 +0200 Subject: [PATCH 4/5] support external signers in wasm --- c/include/in3/plugin.h | 3 ++- c/src/core/client/plugin.h | 3 ++- c/src/pay/zksync/zksync.c | 9 ++++++--- c/src/signer/pk-signer/signer.c | 22 +++++++++++++++++----- c/src/verifier/eth1/basic/sign_tx.c | 6 ++++-- wasm/src/in3.js | 13 +++++++++++-- wasm/src/in3_util.js | 4 ++++ wasm/src/index.d.ts | 7 +++++++ wasm/src/wasm.c | 27 +++++++++++++++++++++++++++ 9 files changed, 80 insertions(+), 14 deletions(-) diff --git a/c/include/in3/plugin.h b/c/include/in3/plugin.h index 578d5de13..b0ac64c39 100644 --- a/c/include/in3/plugin.h +++ b/c/include/in3/plugin.h @@ -208,7 +208,8 @@ typedef enum { */ typedef struct sign_account_ctx { struct in3_ctx* ctx; /**< the context of the request in order report errors */ - address_t account; /**< the account to use for the signature */ + uint8_t* accounts; /**< the account to use for the signature */ + int accounts_len; /**< number of accounts */ in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ } in3_sign_account_ctx_t; diff --git a/c/src/core/client/plugin.h b/c/src/core/client/plugin.h index 578d5de13..b0ac64c39 100644 --- a/c/src/core/client/plugin.h +++ b/c/src/core/client/plugin.h @@ -208,7 +208,8 @@ typedef enum { */ typedef struct sign_account_ctx { struct in3_ctx* ctx; /**< the context of the request in order report errors */ - address_t account; /**< the account to use for the signature */ + uint8_t* accounts; /**< the account to use for the signature */ + int accounts_len; /**< number of accounts */ in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ } in3_sign_account_ctx_t; diff --git a/c/src/pay/zksync/zksync.c b/c/src/pay/zksync/zksync.c index ac4148968..8ec8c87f8 100644 --- a/c/src/pay/zksync/zksync.c +++ b/c/src/pay/zksync/zksync.c @@ -58,9 +58,12 @@ static in3_ret_t send_provider_request(in3_ctx_t* parent, zksync_config_t* conf, static in3_ret_t zksync_get_account(zksync_config_t* conf, in3_ctx_t* ctx, uint8_t** account) { if (!conf->account) { - in3_sign_account_ctx_t sctx = {.ctx = ctx, .account = {0}}; - if (in3_plugin_execute_first(ctx, PLGN_ACT_SIGN_ACCOUNT, &sctx)) return ctx_set_error(ctx, "No account configured or signer set", IN3_ECONFIG); - memcpy(conf->account = _malloc(20), sctx.account, 20); + in3_sign_account_ctx_t sctx = {.ctx = ctx, .accounts = NULL, .accounts_len = 0}; + if (in3_plugin_execute_first(ctx, PLGN_ACT_SIGN_ACCOUNT, &sctx) || !sctx.accounts_len) { + if (sctx.accounts) _free(sctx.accounts); + return ctx_set_error(ctx, "No account configured or signer set", IN3_ECONFIG); + } + conf->account = (uint8_t*) sctx.accounts; } if (account) *account = conf->account; diff --git a/c/src/signer/pk-signer/signer.c b/c/src/signer/pk-signer/signer.c index 3dcca92ff..56f9dcf1b 100644 --- a/c/src/signer/pk-signer/signer.c +++ b/c/src/signer/pk-signer/signer.c @@ -75,7 +75,11 @@ static bool add_key(in3_t* c, bytes32_t pk) { in3_sign_account_ctx_t ctx = {0}; 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 && memcmp(ctx.account, address, 20) == 0) return false; + 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) { + bool is_same_address = memcmp(ctx.accounts, address, 20) == 0; + _free(ctx.accounts); + if (is_same_address) return false; + } } eth_set_pk_signer(c, pk); @@ -104,7 +108,9 @@ static in3_ret_t eth_sign_pk(void* data, in3_plugin_act_t action, void* action_c // generate the address from the key in3_sign_account_ctx_t* ctx = action_ctx; ctx->signer_type = SIGNER_ECDSA; - memcpy(ctx->account, k->account, 20); + ctx->accounts = _malloc(20); + ctx->accounts_len = 1; + memcpy(ctx->accounts, k->account, 20); return IN3_OK; } @@ -182,11 +188,17 @@ static in3_ret_t pk_rpc(void* data, in3_plugin_act_t action, void* action_ctx) { if (strcmp(method, "eth_accounts") == 0) { sb_t* sb = in3_rpc_handle_start(ctx); bool first = true; - in3_sign_account_ctx_t sc = {0}; + in3_sign_account_ctx_t sc = {.ctx = ctx->ctx, .accounts = NULL, .accounts_len = 0, .signer_type = 0}; for (in3_plugin_t* p = ctx->ctx->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) { - sb_add_rawbytes(sb, first ? "[\"0x" : "\",\"0x", bytes(sc.account, 20), 20); - first = false; + 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 ? "[]" : "\"]"); diff --git a/c/src/verifier/eth1/basic/sign_tx.c b/c/src/verifier/eth1/basic/sign_tx.c index b46210555..cbbb01e20 100644 --- a/c/src/verifier/eth1/basic/sign_tx.c +++ b/c/src/verifier/eth1/basic/sign_tx.c @@ -113,9 +113,11 @@ static in3_ret_t get_from_address(d_token_t* tx, in3_ctx_t* ctx, address_t res) // if it is not specified, we rely on the from-address of the signer. if (!in3_plugin_is_registered(ctx->client, PLGN_ACT_SIGN_ACCOUNT)) return ctx_set_error(ctx, "missing from address in tx", IN3_EINVAL); - in3_sign_account_ctx_t actx = {.ctx = ctx, .account = {0}}; + in3_sign_account_ctx_t actx = {.ctx = ctx, .accounts = NULL, .accounts_len = 0}; TRY(in3_plugin_execute_first(ctx, PLGN_ACT_SIGN_ACCOUNT, &actx)) - memcpy(res, actx.account, 20); + if (!actx.accounts) return ctx_set_error(ctx, "no from address found", IN3_EINVAL); + memcpy(res, actx.accounts, 20); + _free(actx.accounts); return IN3_OK; } diff --git a/wasm/src/in3.js b/wasm/src/in3.js index a7529caa9..1c3a7dd02 100644 --- a/wasm/src/in3.js +++ b/wasm/src/in3.js @@ -150,6 +150,15 @@ const aliases = { kovan: '0x2a', tobalaba: '0x44d', main: '0x1', ipfs: '0x7d0', */ class IN3 { + set signer(signer) { + this._signer = signer + if (signer && signer.getAccounts) + this.registerPlugin(signer) + } + get signer() { + return this._signer + } + _ensure_ptr_sync() { if (this.ptr) return let chainId = this.config && this.config.chainId @@ -223,7 +232,7 @@ class IN3 { registerPlugin(plgn) { let action = 0 if (plgn.term) action |= 0x2 - if (plgn.getAccount) action |= 0x20 + if (plgn.getAccounts) action |= 0x20 if (plgn.handleRPC) action |= 0x100 if (plgn.verifyRPC) action |= 0x200 if (plgn.cacheGet) action |= 0x800 @@ -235,7 +244,7 @@ class IN3 { this.plugins.push(plgn) } - if (this.ptr) + if (this.ptr) in3w.ccall('wasm_register_plugin', 'number', ['number', 'number', 'number'], [this.ptr, action, index]); } diff --git a/wasm/src/in3_util.js b/wasm/src/in3_util.js index 71ad4f4e6..dd7183fcd 100644 --- a/wasm/src/in3_util.js +++ b/wasm/src/in3_util.js @@ -568,6 +568,10 @@ class SimpleSigner { if (pks) pks.forEach(_ => this.addAccount(_)) } + getAccounts() { + return Object.keys(this.accounts) + } + addAccount(pk) { const adr = private2address(pk) this.accounts[adr] = toBuffer(pk) diff --git a/wasm/src/index.d.ts b/wasm/src/index.d.ts index 873bd8187..a961f056a 100644 --- a/wasm/src/index.d.ts +++ b/wasm/src/index.d.ts @@ -640,6 +640,9 @@ export declare interface Signer { /** returns true if the account is supported (or unlocked) */ canSign(address: Address): Promise + /** returns all addresses managed by the signer. */ + getAccounts(): Address[] + /** * signing of any data. * if hashFirst is true the data should be hashed first, otherwise the data is the hash. @@ -652,6 +655,10 @@ export declare class SimpleSigner implements Signer, tx: Transaction) => Promise diff --git a/wasm/src/wasm.c b/wasm/src/wasm.c index 8f61513d0..a41f69b90 100644 --- a/wasm/src/wasm.c +++ b/wasm/src/wasm.c @@ -149,6 +149,20 @@ EM_JS(int, plgn_exec_rpc_handle, (in3_t * c, in3_ctx_t* ctx, char* req, int inde return 0; }) +EM_JS(int, plgn_exec_sign_accounts, (in3_t * c, in3_sign_account_ctx_t* sctx, int index), { + var client = Module.clients[c]; + var plgn = client && client.plugins[index]; + if (!plgn) return -4; + try { + var val = plgn.getAccounts(client); + if (val) + in3w.ccall("wasm_set_sign_account", "void", [ "number", "number", "string" ], [ sctx, val.length, '0x' + val.map(function(a){return a.substr(2)}).join("") ]); + } catch (x) { + return -4; + } + return 0; +}) + /** * the main plgn-function which is called for each js-plugin, * delegating it depending on the action. @@ -160,6 +174,10 @@ in3_ret_t wasm_plgn(void* data, in3_plugin_act_t action, void* ctx) { switch (action) { case PLGN_ACT_INIT: return IN3_OK; case PLGN_ACT_TERM: return plgn_exec_term(ctx, index); + case PLGN_ACT_SIGN_ACCOUNT: { + in3_sign_account_ctx_t* sctx = ctx; + return plgn_exec_sign_accounts(sctx->ctx->client, sctx, index); + } case PLGN_ACT_RPC_HANDLE: { // extract the request as string, so we can pass it to js in3_rpc_handle_ctx_t* rc = ctx; @@ -195,6 +213,15 @@ void EMSCRIPTEN_KEEPALIVE wasm_set_request_ctx(in3_ctx_t* ctx, char* req) { in3_cache_add_ptr(&ctx->cache, r)->props = CACHE_PROP_MUST_FREE; // but add the copy to be cleaned when freeing ctx to avoid memory leaks. } +/** + * repareses the request for the context with a new input. + */ +void EMSCRIPTEN_KEEPALIVE wasm_set_sign_account(in3_sign_account_ctx_t* ctx, int len, char* addresses) { + ctx->accounts_len = len; + if (len) + hex_to_bytes(addresses, -1, ctx->accounts = _malloc(len * 20), len * 20); +} + /** * main execute function which generates a json representing the status and all required data to be handled in js. * The resulting string needs to be freed by the caller! From cb1cd1273910c7fc86694eebef0ab5a2ec5df5db Mon Sep 17 00:00:00 2001 From: Simon Jentzsch Date: Wed, 7 Oct 2020 12:08:14 +0200 Subject: [PATCH 5/5] format --- c/include/in3/plugin.h | 6 +++--- c/src/core/client/plugin.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/c/include/in3/plugin.h b/c/include/in3/plugin.h index b0ac64c39..6cfc4af64 100644 --- a/c/include/in3/plugin.h +++ b/c/include/in3/plugin.h @@ -207,10 +207,10 @@ typedef enum { * action context when retrieving the account of a signer. */ typedef struct sign_account_ctx { - struct in3_ctx* ctx; /**< the context of the request in order report errors */ - uint8_t* accounts; /**< the account to use for the signature */ + struct in3_ctx* ctx; /**< the context of the request in order report errors */ + uint8_t* accounts; /**< the account to use for the signature */ int accounts_len; /**< number of accounts */ - in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ + in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ } in3_sign_account_ctx_t; // ----------- SIGN_PREPARE --------------- diff --git a/c/src/core/client/plugin.h b/c/src/core/client/plugin.h index b0ac64c39..6cfc4af64 100644 --- a/c/src/core/client/plugin.h +++ b/c/src/core/client/plugin.h @@ -207,10 +207,10 @@ typedef enum { * action context when retrieving the account of a signer. */ typedef struct sign_account_ctx { - struct in3_ctx* ctx; /**< the context of the request in order report errors */ - uint8_t* accounts; /**< the account to use for the signature */ + struct in3_ctx* ctx; /**< the context of the request in order report errors */ + uint8_t* accounts; /**< the account to use for the signature */ int accounts_len; /**< number of accounts */ - in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ + in3_signer_type_t signer_type; /**< the type of the signer used for this account.*/ } in3_sign_account_ctx_t; // ----------- SIGN_PREPARE ---------------