diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml new file mode 100644 index 000000000..348f2eb3d --- /dev/null +++ b/.github/workflows/ccpp.yml @@ -0,0 +1,43 @@ +name: C/C++ CI + +on: [push] + +jobs: + test_macos: + + runs-on: macOS-latest + + steps: + - uses: actions/checkout@v1 + - name: cmake + run: mkdir build; cd build; cmake -DTEST=true -DJAVA=false -DCMAKE_BUILD_TYPE=Debug .. + - name: make + run: cd build; make + - name: test + run: cd build; make test + + test_ubuntu: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: cmake + run: mkdir build; cd build; cmake -DTEST=true -DJAVA=false -DTRANSPORTS=false -DBUILD_DOC=false -DIN3API=true -DIN3_LIB=false -DCMD=false -DCMAKE_BUILD_TYPE=Debug .. + - name: make + run: cd build; make + - name: test + run: cd build; make test + + test_win: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: cmake + run: mkdir build; cd build; cmake -DTEST=true -DJAVA=false -DTRANSPORTS=false -DBUILD_DOC=false -DIN3API=true -DIN3_LIB=false -DCMD=false -DCMAKE_BUILD_TYPE=Debug .. + - name: make + run: cd build; make tests + - name: test + run: cd build; make test diff --git a/README.md b/README.md index 13681bc4d..6d28ab779 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ decentralized and secure network of remote nodes, enabling trustworthy and fast access to blockchain for a large number of low-performance IoT and mobile devices. - ![in3](in3_image.png) + ![in3](docs/in3_image.png) A more detailed explanation of in3 can be found [here](https://in3.readthedocs.io/en/develop/intro.html). diff --git a/docs/2_examples.md b/docs/2_examples.md index 14d5ec39b..14dccf484 100644 --- a/docs/2_examples.md +++ b/docs/2_examples.md @@ -1,83 +1,864 @@ # Examples -The full list of examples can be found here: https://git.slock.it/in3/c/in3-core/tree/develop/examples/c +### call_a_function -### Creating an Incubed Instance +source : [in3-c/examples/c/call_a_function.c](https://github.com/slockit/in3-c/blob/master/examples/c/call_a_function.c) + +This example shows how to call functions on a smart contract eiither directly or using the api to encode the arguments -creating always follow these steps: ```c -#include // the core client -#include // the full ethereum verifier containing the EVM -#include // transport implementation +/// This example shows how to call functions on a smart contract eiither directly or using the api to encode the arguments -// register verifiers, in this case a full verifier allowing eth_call -// this needs to be called only once. -in3_register_eth_full(); +#include // the core client +#include // wrapper for easier use +#include // the full ethereum verifier containing the EVM +#include // transport implementation +#include +#include +#include -// use curl as the default for sending out requests -// this needs to be called only once. -in3_register_curl(); +static in3_ret_t call_func_rpc(in3_t* c); +static in3_ret_t call_func_api(in3_t* c, address_t contract); -// create new client -in3_t* client = in3_new(); +int main() { + in3_ret_t ret = IN3_OK; -// ready to use ... -``` + // register a chain-verifier for full Ethereum-Support in order to verify eth_call + // this needs to be called only once. + in3_register_eth_full(); -### Calling a Function + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); -```c + // Remove log prefix for readability + in3_log_set_prefix(""); + + // create new incubed client + in3_t* c = in3_new(); // define a address (20byte) address_t contract; // copy the hexcoded string into this address - hex2byte_arr("0x845E484b505443814B992Bf0319A5e8F5e407879", -1, contract, 20); + hex2byte_arr("0x2736D225f85740f42D17987100dc8d58e9e16252", -1, contract, 20); - // ask for the number of servers registered - json_ctx_t* response = eth_call_fn(client, contract, "totalServers():uint256"); + // call function using RPC + ret = call_func_rpc(c); + if (ret != IN3_OK) goto END; + + // call function using API + ret = call_func_api(c, contract); + if (ret != IN3_OK) goto END; + +END: + // clean up + in3_free(c); + return 0; +} + +in3_ret_t call_func_rpc(in3_t* c) { + // prepare 2 pointers for the result. + char *result, *error; - // handle response + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + c, // the configured client + "eth_call", // the rpc-method you want to call. + "[{\"to\":\"0x2736d225f85740f42d17987100dc8d58e9e16252\", \"data\":\"0x15625c5e\"}, \"latest\"]", // the signed raw txn, same as the one used in the API example + &result, // the reference to a pointer which will hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Result: \n%s\n", result); + free(result); + return 0; + } else { + printf("Error sending tx: \n%s\n", error); + free(error); + return IN3_EUNKNOWN; + } +} + +in3_ret_t call_func_api(in3_t* c, address_t contract) { + // ask for the number of servers registered + json_ctx_t* response = eth_call_fn(c, contract, BLKNUM_LATEST(), "totalServers():uint256"); if (!response) { printf("Could not get the response: %s", eth_last_error()); - return; + return IN3_EUNKNOWN; } - // convert the result to a integer - int number_of_servers = d_int(response->result); + // convert the response to a uint32_t, + uint32_t number_of_servers = d_int(response->result); - // don't forget to free the response! + // clean up resources free_json(response); - // out put result - printf("Found %i servers registered : \n", number_of_servers); - - // now we call a function with a complex result... - for (int i = 0; i < number_of_servers; i++) { - - // get all the details for one server. - response = eth_call_fn(c, contract, "servers(uint256):(string,address,uint,uint,uint,address)", to_uint256(i)); + // output + printf("Found %u servers registered : \n", number_of_servers); - // handle error + // read all structs ... + for (uint32_t i = 0; i < number_of_servers; i++) { + response = eth_call_fn(c, contract, BLKNUM_LATEST(), "servers(uint256):(string,address,uint,uint,uint,address)", to_uint256(i)); if (!response) { printf("Could not get the response: %s", eth_last_error()); - return; + return IN3_EUNKNOWN; } - // decode data char* url = d_get_string_at(response->result, 0); // get the first item of the result (the url) bytes_t* owner = d_get_bytes_at(response->result, 1); // get the second item of the result (the owner) uint64_t deposit = d_get_long_at(response->result, 2); // get the third item of the result (the deposit) - // print values - printf("Server %i : %s owner = ", i, url); - ba_print(owner->data, owner->len); + printf("Server %i : %s owner = %02x%02x...", i, url, owner->data[0], owner->data[1]); printf(", deposit = %" PRIu64 "\n", deposit); - // clean up + // free memory free_json(response); } + return 0; +} + +``` + +### get_balance + +source : [in3-c/examples/c/get_balance.c](https://github.com/slockit/in3-c/blob/master/examples/c/get_balance.c) + + get the Balance with the API and also as direct RPC-call + + +```c +/// get the Balance with the API and also as direct RPC-call + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation + +#include + +static void get_balance_rpc(in3_t* in3); +static void get_balance_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify accounts + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + + // get balance using raw RPC call + get_balance_rpc(in3); + + // get balance using API + get_balance_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void get_balance_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_getBalance", // the rpc-method you want to call. + "[\"0xc94770007dda54cF92009BFF0dE90c06F603a09f\", \"latest\"]", // the arguments as json-string + &result, // the reference to a pointer whill hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Balance: \n%s\n", result); + free(result); + } else { + printf("Error getting balance: \n%s\n", error); + free(error); + } +} + +void get_balance_api(in3_t* in3) { + // the address of account whose balance we want to get + address_t account; + hex2byte_arr("0xc94770007dda54cF92009BFF0dE90c06F603a09f", -1, account, 20); + + // get balance of account + long double balance = as_double(eth_getBalance(in3, account, BLKNUM_EARLIEST())); + + // if the result is null there was an error an we can get the latest error message from eth_lat_error() + balance ? printf("Balance: %Lf\n", balance) : printf("error getting the balance : %s\n", eth_last_error()); +} + +``` + +### get_block + +source : [in3-c/examples/c/get_block.c](https://github.com/slockit/in3-c/blob/master/examples/c/get_block.c) + + using the basic-module to get and verify a Block with the API and also as direct RPC-call + + +```c +/// using the basic-module to get and verify a Block with the API and also as direct RPC-call + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation + +#include +#include + +static void get_block_rpc(in3_t* in3); +static void get_block_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify blocks + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + + // get block using raw RPC call + get_block_rpc(in3); + + // get block using API + get_block_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void get_block_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_getBlockByNumber", // the rpc-method you want to call. + "[\"latest\",true]", // the arguments as json-string + &result, // the reference to a pointer whill hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Latest block : \n%s\n", result); + free(result); + } else { + printf("Error verifing the Latest block : \n%s\n", error); + free(error); + } +} + +void get_block_api(in3_t* in3) { + // get the block without the transaction details + eth_block_t* block = eth_getBlockByNumber(in3, BLKNUM(8432424), false); + + // if the result is null there was an error an we can get the latest error message from eth_lat_error() + if (!block) + printf("error getting the block : %s\n", eth_last_error()); + else { + printf("Number of transactions in Block #%llu: %d\n", block->number, block->tx_count); + free(block); + } +} + +``` + +### get_logs + +source : [in3-c/examples/c/get_logs.c](https://github.com/slockit/in3-c/blob/master/examples/c/get_logs.c) + + fetching events and verify them with eth_getLogs + + +```c +/// fetching events and verify them with eth_getLogs + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation + +#include +#include + +static void get_logs_rpc(in3_t* in3); +static void get_logs_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify logs + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + in3->chainId = ETH_CHAIN_ID_KOVAN; + + // get logs using raw RPC call + get_logs_rpc(in3); + + // get logs using API + get_logs_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void get_logs_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_getLogs", // the rpc-method you want to call. + "[{}]", // the arguments as json-string + &result, // the reference to a pointer whill hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Logs : \n%s\n", result); + free(result); + } else { + printf("Error getting logs : \n%s\n", error); + free(error); + } +} + +void get_logs_api(in3_t* in3) { + // Create filter options + char b[30]; + sprintf(b, "{\"fromBlock\":\"0x%" PRIx64 "\"}", eth_blockNumber(in3) - 2); + json_ctx_t* jopt = parse_json(b); + + // Create new filter with options + size_t fid = eth_newFilter(in3, jopt); + + // Get logs + eth_log_t* logs = NULL; + in3_ret_t ret = eth_getFilterLogs(in3, fid, &logs); + if (ret != IN3_OK) { + printf("eth_getFilterLogs() failed [%d]\n", ret); + return; + } + + // print result + while (logs) { + eth_log_t* l = logs; + printf("--------------------------------------------------------------------------------\n"); + printf("\tremoved: %s\n", l->removed ? "true" : "false"); + printf("\tlogId: %lu\n", l->log_index); + printf("\tTxId: %lu\n", l->transaction_index); + printf("\thash: "); + ba_print(l->block_hash, 32); + printf("\n\tnum: %" PRIu64 "\n", l->block_number); + printf("\taddress: "); + ba_print(l->address, 20); + printf("\n\tdata: "); + b_print(&l->data); + printf("\ttopics[%lu]: ", l->topic_count); + for (size_t i = 0; i < l->topic_count; i++) { + printf("\n\t"); + ba_print(l->topics[i], 32); + } + printf("\n"); + logs = logs->next; + free(l->data.data); + free(l->topics); + free(l); + } + eth_uninstallFilter(in3, fid); + free_json(jopt); +} + +``` + +### get_transaction + +source : [in3-c/examples/c/get_transaction.c](https://github.com/slockit/in3-c/blob/master/examples/c/get_transaction.c) + +checking the transaction data + + +```c +/// checking the transaction data + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation + +#include + +static void get_tx_rpc(in3_t* in3); +static void get_tx_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify txs + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + + // get tx using raw RPC call + get_tx_rpc(in3); + + // get tx using API + get_tx_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void get_tx_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_getTransactionByHash", // the rpc-method you want to call. + "[\"0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab5252287c34bc5d12457eab0e\"]", // the arguments as json-string + &result, // the reference to a pointer which will hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Latest tx : \n%s\n", result); + free(result); + } else { + printf("Error verifing the Latest tx : \n%s\n", error); + free(error); + } +} + +void get_tx_api(in3_t* in3) { + // the hash of transaction that we want to get + bytes32_t tx_hash; + hex2byte_arr("0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab5252287c34bc5d12457eab0e", -1, tx_hash, 32); + + // get the tx by hash + eth_tx_t* tx = eth_getTransactionByHash(in3, tx_hash); + + // if the result is null there was an error an we can get the latest error message from eth_last_error() + if (!tx) + printf("error getting the tx : %s\n", eth_last_error()); + else { + printf("Transaction #%d of block #%llx", tx->transaction_index, tx->block_number); + free(tx); + } +} + +``` + +### get_transaction_receipt + +source : [in3-c/examples/c/get_transaction_receipt.c](https://github.com/slockit/in3-c/blob/master/examples/c/get_transaction_receipt.c) + + validating the result or receipt of an transaction + + +```c +/// validating the result or receipt of an transaction + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation + +#include +#include + +static void get_tx_receipt_rpc(in3_t* in3); +static void get_tx_receipt_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify tx receipts + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + + // get tx receipt using raw RPC call + get_tx_receipt_rpc(in3); + + // get tx receipt using API + get_tx_receipt_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void get_tx_receipt_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_getTransactionReceipt", // the rpc-method you want to call. + "[\"0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab5252287c34bc5d12457eab0e\"]", // the arguments as json-string + &result, // the reference to a pointer which will hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Transaction receipt: \n%s\n", result); + free(result); + } else { + printf("Error verifing the tx receipt: \n%s\n", error); + free(error); + } +} + +void get_tx_receipt_api(in3_t* in3) { + // the hash of transaction whose receipt we want to get + bytes32_t tx_hash; + hex2byte_arr("0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab5252287c34bc5d12457eab0e", -1, tx_hash, 32); + + // get the tx receipt by hash + eth_tx_receipt_t* txr = eth_getTransactionReceipt(in3, tx_hash); + + // if the result is null there was an error an we can get the latest error message from eth_last_error() + if (!txr) + printf("error getting the tx : %s\n", eth_last_error()); + else { + printf("Transaction #%d of block #%llx, gas used = %" PRIu64 ", status = %s\n", txr->transaction_index, txr->block_number, txr->gas_used, txr->status ? "success" : "failed"); + free_tx_receipt(txr); + } +} + +``` + +### send_transaction + +source : [in3-c/examples/c/send_transaction.c](https://github.com/slockit/in3-c/blob/master/examples/c/send_transaction.c) + +sending a transaction including signing it with a private key + + +```c +/// sending a transaction including signing it with a private key + +#include // the core client +#include // wrapper for easier use +#include // use the basic module +#include // transport implementation +#include // default signer implementation + +#include + +// fixme: This is only for the sake of demo. Do NOT store private keys as plaintext. +#define ETH_PRIVATE_KEY "0x8da4ef21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41de8f" + +static void send_tx_rpc(in3_t* in3); +static void send_tx_api(in3_t* in3); + +int main() { + + // register a chain-verifier for basic Ethereum-Support, which is enough to verify txs + // this needs to be called only once + in3_register_eth_basic(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* in3 = in3_new(); + + // convert the hexstring to bytes + bytes32_t pk; + hex2byte_arr(ETH_PRIVATE_KEY, -1, pk, 32); + + // create a simple signer with this key + eth_set_pk_signer(in3, pk); + + // send tx using raw RPC call + send_tx_rpc(in3); + + // send tx using API + send_tx_api(in3); + + // cleanup client after usage + in3_free(in3); +} + +void send_tx_rpc(in3_t* in3) { + // prepare 2 pointers for the result. + char *result, *error; + + // send raw rpc-request, which is then verified + in3_ret_t res = in3_client_rpc( + in3, // the configured client + "eth_sendRawTransaction", // the rpc-method you want to call. + "[\"0xf892808609184e72a0008296c094d46e8dd67c5d32be8058bb8eb970870f0724456" + "7849184e72aa9d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb9" + "70870f07244567526a06f0103fccdcae0d6b265f8c38ee42f4a722c1cb36230fe8da40315acc3051" + "9a8a06252a68b26a5575f76a65ac08a7f684bc37b0c98d9e715d73ddce696b58f2c72\"]", // the signed raw txn, same as the one used in the API example + &result, // the reference to a pointer which will hold the result + &error); // the pointer which may hold a error message + + // check and print the result or error + if (res == IN3_OK) { + printf("Result: \n%s\n", result); + free(result); + } else { + printf("Error sending tx: \n%s\n", error); + free(error); + } +} + +void send_tx_api(in3_t* in3) { + // prepare parameters + address_t to, from; + hex2byte_arr("0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377", -1, from, 20); + hex2byte_arr("0xd46e8dd67c5d32be8058bb8eb970870f07244567", -1, to, 20); + + bytes_t* data = hex2byte_new_bytes("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675", 82); + + // send the tx + bytes_t* tx_hash = eth_sendTransaction(in3, from, to, OPTIONAL_T_VALUE(uint64_t, 0x96c0), OPTIONAL_T_VALUE(uint64_t, 0x9184e72a000), OPTIONAL_T_VALUE(uint256_t, to_uint256(0x9184e72a)), OPTIONAL_T_VALUE(bytes_t, *data), OPTIONAL_T_UNDEFINED(uint64_t)); + + // if the result is null there was an error and we can get the latest error message from eth_last_error() + if (!tx_hash) + printf("error sending the tx : %s\n", eth_last_error()); + else { + printf("Transaction hash: "); + b_print(tx_hash); + b_free(tx_hash); + } + b_free(data); +} ``` +### usn_device + +source : [in3-c/examples/c/usn_device.c](https://github.com/slockit/in3-c/blob/master/examples/c/usn_device.c) + +a example how to watch usn events and act upon it. + + +```c +/// a example how to watch usn events and act upon it. + +#include // the core client +#include // wrapper for easier use +#include // the full ethereum verifier containing the EVM +#include // transport implementation +#include // signer-api +#include // api for renting +#include +#include +#include +#if defined(_WIN32) || defined(WIN32) +#include +#else +#include +#endif + +static int handle_booking(usn_event_t* ev) { + printf("\n%s Booking timestamp=%" PRIu64 "\n", ev->type == BOOKING_START ? "START" : "STOP", ev->ts); + return 0; +} + +int main(int argc, char* argv[]) { + + // register a chain-verifier for full Ethereum-Support in order to verify eth_call + // this needs to be called only once. + in3_register_eth_full(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* c = in3_new(); + + // switch to goerli + c->chainId = 0x5; + + // setting up a usn-device-config + usn_device_conf_t usn; + usn.booking_handler = handle_booking; // this is the handler, which is called for each rent/return or start/stop + usn.c = c; // the incubed client + usn.chain_id = c->chainId; // the chain_id + usn.devices = NULL; // this will contain the list of devices supported + usn.len_devices = 0; // and length of this list + usn.now = 0; // the current timestamp + unsigned int wait_time = 5; // the time to wait between the internval + hex2byte_arr("0x85Ec283a3Ed4b66dF4da23656d4BF8A507383bca", -1, usn.contract, 20); // address of the usn-contract, which we copy from hex + + // register a usn-device + usn_register_device(&usn, "office@slockit"); + + // now we run en endless loop which simply wait for events on the chain. + printf("\n start watching...\n"); + while (true) { + usn.now = time(NULL); // update the timestamp, since this is running on embedded devices, this may be depend on the hardware. + unsigned int timeout = usn_update_state(&usn, wait_time) * 1000; // this will now check for new events and trigger the handle_booking if so. + + // sleep +#if defined(_WIN32) || defined(WIN32) + Sleep(timeout); +#else + nanosleep((const struct timespec[]){{0, timeout * 1000000L}}, NULL); +#endif + } + + // clean up + in3_free(c); + return 0; +} +``` + +### usn_rent + +source : [in3-c/examples/c/usn_rent.c](https://github.com/slockit/in3-c/blob/master/examples/c/usn_rent.c) + +how to send a rent transaction to a usn contract usinig the usn-api. + + +```c +/// how to send a rent transaction to a usn contract usinig the usn-api. + +#include // the core client +#include // wrapper for easier use +#include // the full ethereum verifier containing the EVM +#include // transport implementation +#include // signer-api +#include // api for renting +#include +#include + +/** + * takes the keystore json-data and a password and assigns the decrypted key as signer. + */ +void unlock_key(in3_t* c, char* json_data, char* passwd) { + // parse the json + json_ctx_t* key_data = parse_json(json_data); + if (!key_data) { + perror("key is not parseable!\n"); + exit(EXIT_FAILURE); + } + + // decrypt the key + uint8_t* pk = malloc(32); + if (decrypt_key(key_data->result, passwd, pk) != IN3_OK) { + perror("wrong password!\n"); + exit(EXIT_FAILURE); + } + + // free json + free_json(key_data); + + // create a signer with this key + eth_set_pk_signer(c, pk); +} + +int main(int argc, char* argv[]) { + + // register a chain-verifier for full Ethereum-Support in order to verify eth_call + // this needs to be called only once. + in3_register_eth_full(); + + // use curl as the default for sending out requests + // this needs to be called only once. + in3_register_curl(); + + // create new incubed client + in3_t* c = in3_new(); + + // switch to goerli + c->chainId = 0x5; + + // address of the usn-contract, which we copy from hex + address_t contract; + hex2byte_arr("0x85Ec283a3Ed4b66dF4da23656d4BF8A507383bca", -1, contract, 20); + + // read the key from args - I know this is not safe, but this is just a example. + if (argc < 3) { + perror("you need to provide a json-key and password to rent it"); + exit(EXIT_FAILURE); + } + char* key_data = argv[1]; + char* passwd = argv[2]; + unlock_key(c, key_data, passwd); + + // rent it for one hour. + uint32_t renting_seconds = 3600; + + // allocate 32 bytes for the resulting tx hash + bytes32_t tx_hash; + + // start charging + if (usn_rent(c, contract, NULL, "office@slockit", renting_seconds, tx_hash)) + printf("Could not start charging\n"); + else { + printf("Charging tx successfully sent... tx_hash=0x"); + for (int i = 0; i < 32; i++) printf("%02x", tx_hash[i]); + printf("\n"); + + if (argc == 4) // just to include it : if you want to stop earlier, you can call + usn_return(c, contract, "office@slockit", tx_hash); + } + + // clean up + in3_free(c); + return 0; +} +``` + + +### Building + +In order to run those examples, you only need a c-compiler (gcc or clang) and curl installed. + +``` +./build.sh +``` + +will build all examples in this directory. +You can build them individually by executing: + +``` +gcc -o get_block_api get_block_api.c -lin3 -lcurl +``` + diff --git a/docs/3_rpc.md b/docs/3_rpc.md new file mode 100644 index 000000000..b2e6e9d4f --- /dev/null +++ b/docs/3_rpc.md @@ -0,0 +1,183 @@ +# RPC + +The 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. + +- For Ethereum : https://github.com/ethereum/wiki/wiki/JSON-RPC +- For Bitcoin : https://bitcoincore.org/en/doc/0.18.0/ + +The Incbed nodes already add a few special RPC-methods, which are specified in the [RPC-Specification](https://in3.readthedocs.io/en/develop/spec.html#incubed) Section of the Protocol. + +In addition the incubed client itself offers special RPC-Methods, which are mostly handled directly inside the client: + +### in3_config + +changes the configuration of a client. The configuration is passed as the first param and may contain only the values to change. + +Parameters: + +1. `config`: config-object - a Object with config-params. + +The config params support the following properties : + + +* **[autoUpdateList](https://github.com/slockit/in3/blob/master/src/types/types.ts#L255)** :`boolean` *(optional)* - if true the nodelist will be automaticly updated if the lastBlock is newer + example: true + +* **[chainId](https://github.com/slockit/in3/blob/master/src/types/types.ts#L240)** :`string` - servers to filter for the given chain. The chain-id based on EIP-155. + example: 0x1 + +* **[finality](https://github.com/slockit/in3/blob/master/src/types/types.ts#L230)** :`number` *(optional)* - the number in percent needed in order reach finality (% of signature of the validators) + example: 50 + +* **[includeCode](https://github.com/slockit/in3/blob/master/src/types/types.ts#L187)** :`boolean` *(optional)* - 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 + +* **[key](https://github.com/slockit/in3/blob/master/src/types/types.ts#L169)** :`any` *(optional)* - the client key to sign requests + example: 0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7 + +* **[maxAttempts](https://github.com/slockit/in3/blob/master/src/types/types.ts#L182)** :`number` *(optional)* - max number of attempts in case a response is rejected + example: 10 + +* **[maxBlockCache](https://github.com/slockit/in3/blob/master/src/types/types.ts#L197)** :`number` *(optional)* - number of number of blocks cached in memory + example: 100 + +* **[maxCodeCache](https://github.com/slockit/in3/blob/master/src/types/types.ts#L192)** :`number` *(optional)* - number of max bytes used to cache the code in memory + example: 100000 + +* **[minDeposit](https://github.com/slockit/in3/blob/master/src/types/types.ts#L215)** :`number` - min stake of the server. Only nodes owning at least this amount will be chosen. + +* **[nodeLimit](https://github.com/slockit/in3/blob/master/src/types/types.ts#L155)** :`number` *(optional)* - the limit of nodes to store in the client. + example: 150 + +* **[proof](https://github.com/slockit/in3/blob/master/src/types/types.ts#L206)** :`'none'`|`'standard'`|`'full'` *(optional)* - if true the nodes should send a proof of the response + example: true + +* **[replaceLatestBlock](https://github.com/slockit/in3/blob/master/src/types/types.ts#L220)** :`number` *(optional)* - if specified, the blocknumber *latest* will be replaced by blockNumber- specified value + example: 6 + +* **[requestCount](https://github.com/slockit/in3/blob/master/src/types/types.ts#L225)** :`number` - the number of request send when getting a first answer + example: 3 + +* **[rpc](https://github.com/slockit/in3/blob/master/src/types/types.ts#L267)** :`string` *(optional)* - url of one or more rpc-endpoints to use. (list can be comma seperated) + +* **[servers](https://github.com/slockit/in3/blob/master/src/types/types.ts#L271)** *(optional)* - the nodelist per chain + +* **[signatureCount](https://github.com/slockit/in3/blob/master/src/types/types.ts#L211)** :`number` *(optional)* - number of signatures requested + example: 2 + +* **[verifiedHashes](https://github.com/slockit/in3/blob/master/src/types/types.ts#L201)** :`string`[] *(optional)* - if the client sends a 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. + +Returns: + +an boolean confirming that the config has changed. + +Example: + + +Request: +```js +{ + "method":"in3_config", + "params":[{ + "chainId":"0x5", + "maxAttempts":4, + "nodeLimit":10 + "servers":{ + "0x1": [ + "nodeList": [ + { + "address":"0x1234567890123456789012345678901234567890", + "url":"https://mybootnode-A.com", + "props":"0xFFFF", + }, + { + "address":"0x1234567890123456789012345678901234567890", + "url":"https://mybootnode-B.com", + "props":"0xFFFF", + } + ] + ] + } + + }] +} +``` + +Response: + +```js +{ + "id": 1, + "result": true, +} +``` + +### in3_abiEncode + +based on the [ABI-encoding](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html) used by solidity, this function encodes the values and returns it as hex-string. + +Parameters: + +1. `signature`: string - 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. +2. `params`: array - 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. + +Request: + +```js +{ + "method":"in3_abiEncode", + "params":[ + "getBalance(address)", + ["0x1234567890123456789012345678901234567890"] + ] +} +``` + +Response: + +```js +{ + "id": 1, + "result": "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890", +} +``` + + +### in3_abiDecode + +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. + +Parameters: + +1. `signature`: string - 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. +2. `data`: hex - the data to decode (usually the result of a eth_call) + +Returns: + +a array (if more then one arguments in the result-type) or the the value after decodeing. + +Request: + +```js +{ + "method":"in3_abiDecode", + "params":[ + "(address,uint256)", + "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005" + ] +} +``` + +Response: + +```js +{ + "id": 1, + "result": ["0x1234567890123456789012345678901234567890","0x05"], +} +``` \ No newline at end of file diff --git a/docs/build_examples.md_ b/docs/build_examples.md_ new file mode 100644 index 000000000..362fc67d1 --- /dev/null +++ b/docs/build_examples.md_ @@ -0,0 +1,16 @@ + +### Building + +In order to run those examples, you only need a c-compiler (gcc or clang) and curl installed. + +``` +./build.sh +``` + +will build all examples in this directory. +You can build them individually by executing: + +``` +gcc -o get_block_api get_block_api.c -lin3 -lcurl +``` + diff --git a/in3_image.png b/docs/in3_image.png similarity index 100% rename from in3_image.png rename to docs/in3_image.png diff --git a/examples/c/README.md b/examples/c/README.md index 02a3e6237..6a1770c00 100644 --- a/examples/c/README.md +++ b/examples/c/README.md @@ -1,13 +1,26 @@ -# Examples for C +# Examples -- [get_block_rpc](./get_block_rpc.c) - getting a block as raw verfified JSON-RPC-Result using the miniimal verification. - -- [get_block_api](./get_block_api.c) - getting a block as verified structured data using the Eth API - [call_a_function](./call_a_function.c) - This example shows how to call functions on a smart contract + This example shows how to call functions on a smart contract eiither directly or using the api to encode the arguments + +- [get_balance](./get_balance.c) + get the Balance with the API and also as direct RPC-call + +- [get_block](./get_block.c) + using the basic-module to get and verify a Block with the API and also as direct RPC-call + +- [get_logs](./get_logs.c) + fetching events and verify them with eth_getLogs + +- [get_transaction](./get_transaction.c) + checking the transaction data + +- [get_transaction_receipt](./get_transaction_receipt.c) + validating the result or receipt of an transaction + +- [send_transaction](./send_transaction.c) + sending a transaction including signing it with a private key - [usn_device](./usn_device.c) a example how to watch usn events and act upon it. @@ -15,8 +28,7 @@ - [usn_rent](./usn_rent.c) how to send a rent transaction to a usn contract usinig the usn-api. - -## Building +### Building In order to run those examples, you only need a c-compiler (gcc or clang) and curl installed. diff --git a/examples/c/call_a_function.c b/examples/c/call_a_function.c index 396af8a1f..682e935e2 100644 --- a/examples/c/call_a_function.c +++ b/examples/c/call_a_function.c @@ -1,3 +1,5 @@ +/// This example shows how to call functions on a smart contract eiither directly or using the api to encode the arguments + #include // the core client #include // wrapper for easier use #include // the full ethereum verifier containing the EVM diff --git a/examples/c/get_balance.c b/examples/c/get_balance.c index 9aaf6d807..aaffabbcb 100644 --- a/examples/c/get_balance.c +++ b/examples/c/get_balance.c @@ -1,3 +1,5 @@ +/// get the Balance with the API and also as direct RPC-call + #include // the core client #include // wrapper for easier use #include // use the basic module diff --git a/examples/c/get_block.c b/examples/c/get_block.c index 5535c92fb..60c9f9ea0 100644 --- a/examples/c/get_block.c +++ b/examples/c/get_block.c @@ -1,3 +1,5 @@ +/// using the basic-module to get and verify a Block with the API and also as direct RPC-call + #include // the core client #include // wrapper for easier use #include // use the basic module diff --git a/examples/c/get_logs.c b/examples/c/get_logs.c index 1f4c527a3..63b7ba135 100644 --- a/examples/c/get_logs.c +++ b/examples/c/get_logs.c @@ -1,3 +1,5 @@ +/// fetching events and verify them with eth_getLogs + #include // the core client #include // wrapper for easier use #include // use the basic module diff --git a/examples/c/get_transaction.c b/examples/c/get_transaction.c index 12aa98163..d4d0f4f75 100644 --- a/examples/c/get_transaction.c +++ b/examples/c/get_transaction.c @@ -1,3 +1,5 @@ +/// checking the transaction data + #include // the core client #include // wrapper for easier use #include // use the basic module diff --git a/examples/c/get_transaction_receipt.c b/examples/c/get_transaction_receipt.c index 9fae4e77b..9aa414aa2 100644 --- a/examples/c/get_transaction_receipt.c +++ b/examples/c/get_transaction_receipt.c @@ -1,3 +1,5 @@ +/// validating the result or receipt of an transaction + #include // the core client #include // wrapper for easier use #include // use the basic module diff --git a/examples/c/send_transaction.c b/examples/c/send_transaction.c index 551650dd8..223f645d3 100644 --- a/examples/c/send_transaction.c +++ b/examples/c/send_transaction.c @@ -1,3 +1,5 @@ +/// sending a transaction including signing it with a private key + #include // the core client #include // wrapper for easier use #include // use the basic module @@ -25,8 +27,11 @@ int main() { // create new incubed client in3_t* in3 = in3_new(); + // convert the hexstring to bytes bytes32_t pk; hex2byte_arr(ETH_PRIVATE_KEY, -1, pk, 32); + + // create a simple signer with this key eth_set_pk_signer(in3, pk); // send tx using raw RPC call diff --git a/examples/c/usn_device.c b/examples/c/usn_device.c index ce3cc8045..b6f78f11e 100644 --- a/examples/c/usn_device.c +++ b/examples/c/usn_device.c @@ -1,3 +1,5 @@ +/// a example how to watch usn events and act upon it. + #include // the core client #include // wrapper for easier use #include // the full ethereum verifier containing the EVM diff --git a/examples/c/usn_rent.c b/examples/c/usn_rent.c index 750e48beb..ff9c75d25 100644 --- a/examples/c/usn_rent.c +++ b/examples/c/usn_rent.c @@ -1,3 +1,5 @@ +/// how to send a rent transaction to a usn contract usinig the usn-api. + #include // the core client #include // wrapper for easier use #include // the full ethereum verifier containing the EVM diff --git a/scripts/update_examples.sh b/scripts/update_examples.sh new file mode 100755 index 000000000..088567cad --- /dev/null +++ b/scripts/update_examples.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +DOC="../../docs/2_examples.md" +README="README.md" + +cd ../examples/c + +printf "# Examples\n\n" > $DOC +printf "# Examples\n\n" > $README + +for f in *.c; + do + printf "### ${f%%.*}\n\nsource : [in3-c/examples/c/$f](https://github.com/slockit/in3-c/blob/master/examples/c/$f)\n\n" >> $DOC + cat $f | grep ^/// | sed "s/\/\/\/ //g" >> $DOC + printf "\n\n\`\`\`c\n" >> $DOC + cat $f >> $DOC + printf "\n\`\`\`\n\n" >> $DOC + + printf "\n- [${f%%.*}](./$f)\n " >> $README + cat $f | grep ^/// | sed "s/\/\/\/ //g" >> $README +done + +cat ../../docs/build_examples.md_ >> $DOC +cat ../../docs/build_examples.md_ >> $README + diff --git a/src/api/eth1/rpc_api.c b/src/api/eth1/rpc_api.c index c1b860734..520c059ae 100644 --- a/src/api/eth1/rpc_api.c +++ b/src/api/eth1/rpc_api.c @@ -57,45 +57,73 @@ static in3_verify parent_verify = NULL; static in3_pre_handle parent_handle = NULL; +static in3_ret_t in3_abiEncode(in3_ctx_t* ctx, d_token_t* params, in3_response_t** response) { + RESPONSE_START(); + call_request_t* req = parseSignature(d_get_string_at(params, 0)); + if (!req) return ctx_set_error(ctx, "invalid function signature", IN3_EINVAL); + + d_token_t* para = d_get_at(params, 1); + if (!para) { + req_free(req); + return ctx_set_error(ctx, "invalid json data", IN3_EINVAL); + } + + if (set_data(req, para, req->in_data) < 0) { + req_free(req); + return ctx_set_error(ctx, "invalid input data", IN3_EINVAL); + } + sb_add_bytes(&response[0]->result, NULL, &req->call_data->b, 1, false); + RESPONSE_END(); + return IN3_OK; +} +static in3_ret_t in3_abiDecode(in3_ctx_t* ctx, d_token_t* params, in3_response_t** response) { + RESPONSE_START(); + char* sig = d_get_string_at(params, 0); + char full_sig[strlen(sig) + 10]; + if (strstr(sig, ":")) + strcpy(full_sig, sig); + else + sprintf(full_sig, "test():%s", sig); + + call_request_t* req = parseSignature(full_sig); + if (!req) return ctx_set_error(ctx, "invalid function signature", IN3_EINVAL); + + json_ctx_t* res = req_parse_result(req, d_to_bytes(d_get_at(params, 1))); + req_free(req); + if (!res) + return ctx_set_error(ctx, "the input data can not be decoded", IN3_EINVAL); + char* result = d_create_json(res->result); + sb_add_chars(&response[0]->result, result); + free_json(res); + _free(result); + + RESPONSE_END(); + printf(":::%s:::\n", response[0]->result.data); + return IN3_OK; +} +static in3_ret_t in3_config(in3_ctx_t* ctx, d_token_t* params, in3_response_t** response) { + str_range_t r = d_to_json(d_get_at(params, 0)); + char old = r.data[r.len]; + r.data[r.len] = 0; + in3_ret_t ret = in3_configure(ctx->client, r.data); + r.data[r.len] = old; + if (ret) return ctx_set_error(ctx, "Invalid config", ret); + + RESPONSE_START(); + sb_add_chars(&response[0]->result, "true"); + RESPONSE_END(); + return IN3_OK; +} + static in3_ret_t eth_handle_intern(in3_ctx_t* ctx, in3_response_t** response) { if (ctx->len > 1) return IN3_ENOTSUP; // internal handling is only possible for single requests (at least for now) d_token_t* r = ctx->requests[0]; char* method = d_get_stringk(r, K_METHOD); d_token_t* params = d_get(r, K_PARAMS); - // abi encode - if (strcmp(method, "in3_abiEncode") == 0) { - RESPONSE_START(); - call_request_t* req = parseSignature(d_get_string_at(params, 0)); - if (!req) return ctx_set_error(ctx, "invalid function signature", IN3_EINVAL); - - d_token_t* para = d_get_at(params, 1); - if (!para) { - req_free(req); - return ctx_set_error(ctx, "invalid json data", IN3_EINVAL); - } - - if (set_data(req, para, req->in_data) < 0) { - req_free(req); - return ctx_set_error(ctx, "invalid input data", IN3_EINVAL); - } - sb_add_bytes(&response[0]->result, NULL, &req->call_data->b, 1, false); - RESPONSE_END(); - } - - // config - if (strcmp(method, "in3_config") == 0) { - str_range_t r = d_to_json(d_get_at(params, 0)); - char old = r.data[r.len]; - r.data[r.len] = 0; - in3_ret_t ret = in3_configure(ctx->client, r.data); - r.data[r.len] = old; - if (ret) return ctx_set_error(ctx, "Invalid config", ret); - - RESPONSE_START(); - sb_add_chars(&response[0]->result, "true"); - RESPONSE_END(); - } + if (strcmp(method, "in3_abiEncode") == 0) return in3_abiEncode(ctx, params, response); + if (strcmp(method, "in3_abiDecode") == 0) return in3_abiDecode(ctx, params, response); + if (strcmp(method, "in3_config") == 0) return in3_config(ctx, params, response); return parent_handle ? parent_handle(ctx, response) : IN3_OK; } @@ -105,6 +133,7 @@ static int verify(in3_vctx_t* v) { if (!method) return vc_err(v, "no method in the request!"); if (strcmp(method, "in3_abiEncode") == 0 || + strcmp(method, "in3_abiDecode") == 0 || strcmp(method, "in3_config") == 0) return IN3_OK; @@ -126,3 +155,14 @@ void in3_register_eth_api() { in3_register_verifier(v); } } + +// needed rpcs +/* +in3_send +in3_call +in3_pk2address +in3_pk2public +in3_ecrecover +in3_key + +*/ \ No newline at end of file diff --git a/src/cmd/in3/main.c b/src/cmd/in3/main.c index 7dbac26e1..a0a800c6e 100644 --- a/src/cmd/in3/main.c +++ b/src/cmd/in3/main.c @@ -90,6 +90,7 @@ void show_help(char* name) { -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\ -debug if given incubed will output debug information when executing. \n\ +-q quit. no additional output. \n\ -ri read response from stdin \n\ -ro write raw response to stdout \n\ -version displays the version \n\ @@ -269,7 +270,7 @@ static void execute(in3_t* c, FILE* f) { printf("{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":%s}\n", id, r); _free(r); } else - printf("{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":%s}\n", id, ctx->error == NULL ? "Unknown error" : ctx->error); + printf("{\"jsonrpc\":\"2.0\",\"id\":%i,\"error\":\"%s\"}\n", id, ctx->error == NULL ? "Unknown error" : ctx->error); } free_ctx(ctx); first = 0; @@ -606,6 +607,8 @@ int main(int argc, char* argv[]) { c->transport = test_transport; } 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) @@ -692,6 +695,7 @@ int main(int argc, char* argv[]) { // 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); return EXIT_SUCCESS; } diff --git a/src/verifier/eth1/basic/signer.h b/src/verifier/eth1/basic/signer.h index 0ea7f6f70..11d6f5705 100644 --- a/src/verifier/eth1/basic/signer.h +++ b/src/verifier/eth1/basic/signer.h @@ -42,6 +42,11 @@ #include "../../../core/client/client.h" +/** + * simply signer with one private key. + * + * since the pk pointting to the 32 byte private key is not cloned, please make sure, you manage memory allocation correctly! + */ in3_ret_t eth_set_pk_signer(in3_t* in3, bytes32_t pk); #endif diff --git a/test/bindings/wasm/benchmarks.js b/test/bindings/wasm/benchmarks.js new file mode 100644 index 000000000..cdc831162 --- /dev/null +++ b/test/bindings/wasm/benchmarks.js @@ -0,0 +1,57 @@ +/******************************************************************************* + * This file is part of the Incubed project. + * Sources: https://github.com/slockit/in3 + * + * 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 . + *******************************************************************************/ + +const { IN3 } = require('./util/mocker') +const { keccak256 } = require('eth-lib/lib/hash') + +function testHash(fn, l = 1000) { + const start = Date.now() + let init = "0x1234567890123456789012345678901234567890123456789012345678901234" + for (let i = 0; i < l; i++) { + init = fn(init); + } + const s = Date.now() - start + return s +} +let j1 = 0, j2 = 0, w1 = 0, w2 = 0 +const l2 = 100000 +console.log("eth-lib1:", j1 = testHash(keccak256)) +console.log("eth-lib2:", j2 = testHash(keccak256, l2)) +IN3.onInit(() => { + console.log("in3-wasm1:", w1 = testHash(IN3.util.keccak)) + console.log("in3-wasm2:", w2 = testHash(IN3.util.keccak, l2)) + + console.log("1 : " + (j1 / w1).toFixed(1) + ' times faster ') + console.log("2 : " + (j2 / w2).toFixed(1) + ' times faster ') +}) diff --git a/test/bindings/wasm/package.json b/test/bindings/wasm/package.json index bd2185c24..86fb7e73a 100644 --- a/test/bindings/wasm/package.json +++ b/test/bindings/wasm/package.json @@ -5,9 +5,10 @@ "main": "js/src/index.js", "scripts": { "build": "tsc -p .", - "test": "mocha --timeout 5000 --full-trace testRunner.js testApi.js", - "test_api": "mocha --timeout 5000 --full-trace testApi.js", - "test_all": "mocha --timeout 5000 --full-trace *.js" + "test": "mocha --timeout 15000 --full-trace testRunner.js testApi.js", + "test_api": "mocha --timeout 15000 --full-trace testApi.js", + "test_fail": "mocha --timeout 15000 --full-trace testApi.js testRunner.js ", + "test_all": "mocha --timeout 15000 --full-trace *.js" }, "nyc": { "include": [ @@ -45,6 +46,7 @@ "dependencies": { "bn.js": "^5.0.0", "buffer": "^5.2.1", + "eth-lib": "^0.2.8", "in3-common": "^2.0.3-RC1" }, "keywords": [ @@ -55,4 +57,4 @@ "client", "jsonrpc" ] -} \ No newline at end of file +}