diff --git a/.codeclimate.yml b/.codeclimate.yml
index 4e38504f8..fee31eafd 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -17,13 +17,32 @@ plugins:
enabled: true
fixme:
enabled: true
+checks:
+ argument-count:
+ config:
+ threshold: 7
+ file-lines:
+ config:
+ threshold: 400
+ method-complexity:
+ config:
+ threshold: 25
+ method-lines:
+ config:
+ threshold: 70
+ return-statements:
+ config:
+ threshold: 10
+ method-count:
+ config:
+ threshold: 40
exclude_patterns:
- config/
- db/
- dist/
- features/
- "**/node_modules/"
- - script/
+ - scripts/
- "**/spec/"
- "**/test/"
- "**/tests/"
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fc5a4839c..7101adb16 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,25 @@
+###########################################################
+# General CI rules:
+# * Create one CI.yml file per language/purpose
+# * Include said CI.yml file below
+# * We use rules in this CI, which means you cannot use only/except
+# * The workflow rules define when the CI gets triggered, job rules are used to define when jobs get triggered
+# * Do not commit any keys/ethereum addresses/private keys/etc directly, use environment variables or other methods
+# * Thank you for reading this far! Get yourself a chocolate as a treat.
+###########################################################
+
variables:
COMMIT_IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
RELEASE_IMAGE_TAG: $CI_REGISTRY_IMAGE:latest
+# Done to fix this bug: https://gitlab.com/gitlab-org/gitlab/issues/30111#note_275012413
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_IID
+ when: never
+ - when: always
+
+# defines all the stages in the CI, this includes all stages defined inside the included yml files
stages:
- build
- bindings
@@ -15,8 +33,9 @@ stages:
- deploy
- release
+# all the CI files to include and run, they are imported before the CI is started
include:
- - template: Code-Quality.gitlab-ci.yml
+ - local: "code-quality.gitlab-ci.yml"
- local: "/c/ci.yml"
- local: "/c/ci-analyse.yml"
- local: "/c/ci-deploy.yml"
@@ -25,8 +44,3 @@ include:
- local: "/python/ci.yml"
- local: "/dotnet/ci.yml"
- local: "/rust/ci.yml"
-##### local_docker_deploy_and_vulnerability_analysis #####
-
-##### analyse #####
-
-##### deploy #####
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 7a6006585..9594115cb 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -87,6 +87,20 @@
"program": "${workspaceFolder}/build/test/test_ethapi",
"cwd": "${workspaceFolder}/build"
},
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "run tx example",
+ "program": "${workspaceFolder}/c/examples/send_transaction",
+ "cwd": "${workspaceFolder}/c/examples"
+ },
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "run sign test",
+ "program": "${workspaceFolder}/build/test/test_sign",
+ "cwd": "${workspaceFolder}/build"
+ },
{
"type": "lldb",
"request": "launch",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 56e0cf803..937a2b193 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,10 +64,12 @@ 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(DEV_NO_INTRN_PTR "(*dev option*) if true the client will NOT include a void pointer (named internal) for use by devs)" ON)
+option(LEDGER_NANO "include support for nano ledger" OFF)
if (USE_PRECOMPUTED_EC)
ADD_DEFINITIONS(-DUSE_PRECOMPUTED_CP=1)
@@ -119,6 +121,13 @@ if(IPFS)
set(IN3_VERIFIER ${IN3_VERIFIER} ipfs)
endif()
+if(LEDGER_NANO AND ( NOT (WIN32 OR MSVC OR MSYS OR MINGW )))
+ add_definitions(-DLEDGER_NANO)
+ set(HIDAPI true)
+else()
+ set(HIDAPI false)
+endif()
+
if(COLOR AND NOT (MSVC OR MSYS OR MINGW))
ADD_DEFINITIONS(-DLOG_USE_COLOR)
endif()
diff --git a/Dockerfile b/Dockerfile
index b1d83cf6f..ee3a43357 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -40,7 +40,7 @@ RUN cd /in3/ && rm -rf build;
RUN cd /in3/ && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=MINSIZEREL -DIN3_SERVER=true -DUSE_CURL=false .. && make in3
-FROM alpine:latest
+FROM alpine:edge
COPY --from=build /in3/build/bin/in3 /bin/in3
EXPOSE 8545
ENTRYPOINT ["/bin/in3"]
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
index b185e70d2..fe5df9c83 100644
--- a/c/CMakeLists.txt
+++ b/c/CMakeLists.txt
@@ -32,21 +32,33 @@
# with this program. If not, see .
###############################################################################
-
include("${PROJECT_SOURCE_DIR}/c/compiler.cmake")
# build modules
add_subdirectory(src/third-party)
+
+
+if (GCC_ANALYZER)
+ add_compile_options(-fanalyzer -Werror)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fanalyzer -Werror")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fanalyzer -Werror")
+endif()
+
add_subdirectory(src/core)
add_subdirectory(src/transport)
add_subdirectory(src/verifier)
+
+if( LEDGER_NANO AND HIDAPI )
+ add_subdirectory(src/signer/ledger-nano/signer)
+endif()
+
add_subdirectory(src/pay)
add_subdirectory(src/api)
IF (ETH_FULL)
add_subdirectory(src/cmd)
endif()
add_subdirectory(docs)
-
+link_directories(${CMAKE_BINARY_DIR}/lib/)
# create the library
@@ -104,13 +116,21 @@ if (IN3_LIB)
if (USE_SCRYPT)
set(IN3_LIBS ${IN3_LIBS} $)
endif()
+
+
# create the 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 AND HIDAPI )
+ target_link_libraries(in3_lib ${IN3_TRANSPORT} ledger_signer)
+ else()
+ target_link_libraries(in3_lib ${IN3_TRANSPORT} )
+ endif()
+
# install
INSTALL(TARGETS in3_bundle
diff --git a/c/ci-analyse.yml b/c/ci-analyse.yml
index c8d231afa..faebbf575 100644
--- a/c/ci-analyse.yml
+++ b/c/ci-analyse.yml
@@ -1,7 +1,16 @@
+.only_full:
+ rules:
+ - changes:
+ - c/**/*
+ - 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"'
+
coverage:
stage: analysis
image: silkeh/clang:dev
coverage: '/TOTAL.*\s+(\d+.\d+\%)\s*$/'
+ extends: .only_full
needs: []
tags:
- short-jobs
@@ -18,16 +27,17 @@ coverage:
clangcheck:
stage: analysis
- image: docker.slock.it/build-images/cmake:clang10
+ image: docker.slock.it/build-images/cmake:clang11
needs: []
+ extends: .only_full
allow_failure: false
tags:
- short-jobs
script:
- mkdir _build
- cd _build
- - scan-build-10 cmake -DTAG_VERSION=$CI_COMMIT_TAG -DCMAKE_BUILD_TYPE=DEBUG -DIN3_SERVER=true ..
- - scan-build-10 --status-bugs --exclude ../c/src/third-party --force-analyze-debug-code -o ../report make
+ - scan-build-11 cmake -DTAG_VERSION=$CI_COMMIT_TAG -DCMAKE_BUILD_TYPE=DEBUG -DIN3_SERVER=true ..
+ - scan-build-11 --status-bugs --exclude ../c/src/third-party --force-analyze-debug-code -o ../report make
artifacts:
paths:
- report
@@ -35,6 +45,7 @@ clangcheck:
cppcheck:
stage: analysis
image: docker.slock.it/build-images/cmake:gcc-x86-static-analysis
+ extends: .only_full
allow_failure: true
needs: []
tags:
@@ -46,9 +57,24 @@ cppcheck:
- cd ..
- cppcheck --project=_build/compile_commands.json -i/builds/in3/c/in3-core/c/test/unity -i/builds/in3/c/in3-core/c/src/third-party
+gcc10check:
+ stage: analysis
+ image: docker.slock.it/build-images/cmake:gcc10
+ extends: .only_full
+ allow_failure: true
+ needs: []
+ tags:
+ - short-jobs
+ script:
+ - mkdir _build
+ - cd _build
+ - cmake -DGCC_ANALYZER=true ..
+ - make
+
valgrind:
stage: analysis
image: docker.slock.it/build-images/cmake:valgrind
+ extends: .only_full
# allow_failure: true
needs: []
tags:
@@ -64,10 +90,10 @@ valgrind:
- for f in test/test*; do valgrind $VALGRIND_OPTS $(pwd)/$f; done
code_quality:
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/'
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ - if: '$CI_COMMIT_BRANCH == "develop"'
stage: analysis
needs: []
tags:
@@ -83,11 +109,11 @@ code_quality:
format:
stage: analysis
needs: []
- image: docker.slock.it/build-images/cmake:clang10
+ image: docker.slock.it/build-images/cmake:clang11
tags:
- short-jobs
script:
- - find c/src/core/ c/src/cmd/ c/src/api/ c/src/verifier/ c/src/transport/ java \( -name "*.c" -o -name "*.h" -o -name "*.java" \) | xargs clang-format-10 -i
+ - find c/src/core/ c/src/cmd/ c/src/api/ c/src/verifier/ c/src/transport/ java \( -name "*.c" -o -name "*.h" -o -name "*.java" \) | xargs clang-format-11 -i
- git diff --patch --exit-code
cpd:
@@ -102,7 +128,13 @@ cpd:
- cpd --minimum-tokens 150 --language python --files python
vulnerabilities:
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/'
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ - if: '$CI_COMMIT_BRANCH == "develop"'
stage: analysis
+ extends: .only_full
+ allow_failure: true
needs:
- docker
tags:
diff --git a/c/ci-deploy.yml b/c/ci-deploy.yml
index 6973e6972..0af88784d 100644
--- a/c/ci-deploy.yml
+++ b/c/ci-deploy.yml
@@ -1,13 +1,23 @@
+# This template should be used for jobs to run during deployment only
+.only_deploy:
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/'
+ when: manual
+
+.only_full:
+ rules:
+ - changes:
+ - c/**/*
+ - 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"'
+
dockerhub-deploy:
stage: deploy
needs: []
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
+ extends: .only_deploy
tags:
- short-jobs
- when: manual
services:
- docker:dind
image: docker.slock.it/build-images/deployment
@@ -28,6 +38,7 @@ readthedocs:
needs:
- gcc8
- python
+ extends: .only_full
tags:
- short-jobs
allow_failure: true
@@ -58,11 +69,7 @@ release_mac_and_wasm:
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- mac_os
- gcc8
@@ -82,7 +89,7 @@ release_mac_and_wasm:
- cp -r ../wasm_build/module wasm/release-wasm
- cp -r ../asmjs_build/module wasm/release-asmjs
- cp ../java_build/lib/in3.jar lib/in3.jar
- - cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
+ - cp ../python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- cd ..
- tar -zcv --exclude=*cmake* -f in3_${CI_COMMIT_TAG}_mac.tar.gz in3-mac-wasm/
- IPFS_RESPONSE=$(curl -X POST https://api.pinata.cloud/pinning/pinFileToIPFS -H 'Content-Type:multipart/form-data' -H 'pinata_api_key:'"$PINATA_API_KEY" -H 'pinata_secret_api_key:'"$PINATA_SECRET_API_KEY" -F file=@in3_${CI_COMMIT_TAG}_mac.tar.gz -F 'pinataMetadata={"name":"in3_'${CI_COMMIT_TAG}'_mac.tar.gz","keyValues":{"version":"${CI_COMMIT_TAG}"}}' -F 'pinataOptions={"cidVersion":0}')
@@ -110,11 +117,7 @@ release_x64:
- asmjs
- java
- python
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
script:
- export IMAGE_VERSION=$(echo ${CI_COMMIT_TAG} | grep -E '\d+.*' -o)
- mkdir in3-x64
@@ -126,7 +129,7 @@ release_x64:
- cp -r ../wasm_build/module wasm/release-wasm
- cp -r ../asmjs_build/module wasm/release-asmjs
- cp ../java_build/lib/in3.jar lib/in3.jar
- - cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
+ - cp ../python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- cd ..
- tar -zcv --exclude=*cmake* -f in3_${CI_COMMIT_TAG}_x64.tar.gz in3-x64/
- IPFS_RESPONSE=$(curl -X POST https://api.pinata.cloud/pinning/pinFileToIPFS -H 'Content-Type:multipart/form-data' -H 'pinata_api_key:'"$PINATA_API_KEY" -H 'pinata_secret_api_key:'"$PINATA_SECRET_API_KEY" -F file=@in3_${CI_COMMIT_TAG}_x64.tar.gz -F 'pinataMetadata={"name":"in3_'${CI_COMMIT_TAG}'_mac.tar.gz","keyValues":{"version":"${CI_COMMIT_TAG}"}}' -F 'pinataOptions={"cidVersion":0}')
@@ -143,11 +146,7 @@ release_x86:
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- gcc8
- gcc8-x86
@@ -167,7 +166,7 @@ release_x86:
- cp -r ../wasm_build/module wasm/release-wasm
- cp -r ../asmjs_build/module wasm/release-asmjs
- cp ../java_build/lib/in3.jar lib/in3.jar
- - cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
+ - cp ../python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- cd ..
- tar -zcv --exclude=*cmake* -f in3_${CI_COMMIT_TAG}_x86.tar.gz in3-x86/
- IPFS_RESPONSE=$(curl -X POST https://api.pinata.cloud/pinning/pinFileToIPFS -H 'Content-Type:multipart/form-data' -H 'pinata_api_key:'"$PINATA_API_KEY" -H 'pinata_secret_api_key:'"$PINATA_SECRET_API_KEY" -F file=@in3_${CI_COMMIT_TAG}_x86.tar.gz -F 'pinataMetadata={"name":"in3_'${CI_COMMIT_TAG}'_x86.tar.gz","keyValues":{"version":"${CI_COMMIT_TAG}"}}' -F 'pinataOptions={"cidVersion":0}')
@@ -184,11 +183,7 @@ release_arm7:
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- gcc8
- arm7
@@ -208,7 +203,7 @@ release_arm7:
- cp -r ../wasm_build/module wasm/release-wasm
- cp -r ../asmjs_build/module wasm/release-asmjs
- cp ../java_build/lib/in3.jar lib/in3.jar
- - cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
+ - cp ../python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- cd ..
- tar -zcv --exclude=*cmake* -f in3_${CI_COMMIT_TAG}_arm7.tar.gz in3-arm7/
- IPFS_RESPONSE=$(curl -X POST https://api.pinata.cloud/pinning/pinFileToIPFS -H 'Content-Type:multipart/form-data' -H 'pinata_api_key:'"$PINATA_API_KEY" -H 'pinata_secret_api_key:'"$PINATA_SECRET_API_KEY" -F file=@in3_${CI_COMMIT_TAG}_arm7.tar.gz -F 'pinataMetadata={"name":"in3_'${CI_COMMIT_TAG}'_arm7.tar.gz","keyValues":{"version":"${CI_COMMIT_TAG}"}}' -F 'pinataOptions={"cidVersion":0}')
@@ -225,11 +220,7 @@ release_win:
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- gcc8
- win_mingw
@@ -253,7 +244,7 @@ release_win:
- cp -r ../wasm_build/module wasm/release-wasm
- cp -r ../asmjs_build/module wasm/release-asmjs
- cp ../java_build/lib/in3.jar lib/in3.jar
- - cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
+ - cp ../python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- cd ..
- tar -zcv --exclude=*cmake* -f in3_${CI_COMMIT_TAG}_windows.tar.gz in3-win/
- IPFS_RESPONSE=$(curl -X POST https://api.pinata.cloud/pinning/pinFileToIPFS -H 'Content-Type:multipart/form-data' -H 'pinata_api_key:'"$PINATA_API_KEY" -H 'pinata_secret_api_key:'"$PINATA_SECRET_API_KEY" -F file=@in3_${CI_COMMIT_TAG}_windows.tar.gz -F 'pinataMetadata={"name":"in3_'${CI_COMMIT_TAG}'_windows.tar.gz","keyValues":{"version":"${CI_COMMIT_TAG}"}}' -F 'pinataOptions={"cidVersion":0}')
@@ -265,30 +256,12 @@ release_win:
paths:
- in3-win
-release_maven:
- stage: deploy
- image: docker.slock.it/build-images/maven-deployment-image:latest
- tags:
- - short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
- needs:
- - java
- script:
- - touch settings.xml
- - echo $MAVEN_SETTINGS > settings.xml
- - mvn -s settings.xml deploy:deploy-file -DgroupId=it.slock -DartifactId=in3 -Dversion=$CI_COMMIT_TAG -Dpackaging=jar -Dfile=java_build/lib/in3.jar -DrepositoryId=github -Durl=https://maven.pkg.github.com/slockit/in3-c
-
pages:
stage: deploy
tags:
- arm
- only:
- refs:
- - develop
+ rules:
+ - if: '$CI_COMMIT_REF_NAME == "develop"'
needs:
- arm7
- readthedocs
@@ -304,7 +277,7 @@ pages:
- cp -r cov_build/ccov/all-merged public/coverage
- cp -r report/* public/code_analysis
- cp -r doc/build public/rtd
- - cp -r vulnerability_analysis.json public/vulnerability_analysis.json
+ - cp -r vulnerability_analysis.json public/vulnerability_analysis.json || true
- cp -r java/build/reports/jacoco/test/html public/coverage_java
- echo "Incubed report for last build " > public/index.html
artifacts:
@@ -325,7 +298,6 @@ pages:
- java_linux
- java_macos
- readthedocs
- when: manual
script:
- mv scripts/debian .
- mv debian/changelog-in3 debian/changelog
@@ -352,24 +324,18 @@ pages:
debian_package_deploy_bionic:
extends:
- .debian_package_deploy_template_in3
+ - .only_deploy
variables:
DISTRO: "bionic"
VERSION: $CI_COMMIT_TAG
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
debian_package_deploy_disco:
extends:
- .debian_package_deploy_template_in3
+ - .only_deploy
variables:
DISTRO: "disco"
VERSION: $CI_COMMIT_TAG
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
.debian_package_deploy_template_in3_dev:
image: docker.slock.it/build-images/cmake:gcc8-with-debian-deps
@@ -385,7 +351,6 @@ debian_package_deploy_disco:
- java_linux
- java_macos
- readthedocs
- when: manual
script:
- mv scripts/debian .
- mv debian/changelog-dev debian/changelog
@@ -412,35 +377,25 @@ debian_package_deploy_disco:
debian_dev_package_deploy_bionic:
extends:
- .debian_package_deploy_template_in3_dev
+ - .only_deploy
variables:
DISTRO: "bionic"
VERSION: $CI_COMMIT_TAG
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
debian__dev_package_deploy_disco:
extends:
- .debian_package_deploy_template_in3_dev
+ - .only_deploy
variables:
DISTRO: "disco"
VERSION: $CI_COMMIT_TAG
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
brew_release:
stage: release
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- mac_os
- release_mac_and_wasm
@@ -463,11 +418,7 @@ github_body_release:
image: docker.slock.it/build-images/deployment
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
- when: manual
+ extends: .only_deploy
needs:
- release_mac_and_wasm
- release_x64
diff --git a/c/ci.yml b/c/ci.yml
index 82cfe9505..4b5ac53ba 100644
--- a/c/ci.yml
+++ b/c/ci.yml
@@ -1,3 +1,11 @@
+.only_full:
+ rules:
+ - changes:
+ - c/**/*
+ - 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"'
+
.conanbuild:
stage: build
needs: []
@@ -42,7 +50,9 @@ gcc8:
win_mingw:
image: docker.slock.it/build-images/cmake:gcc7-mingw
- extends: .conanbuild
+ extends:
+ - .conanbuild
+ - .only_full
variables:
CONAN_OPTS: "-DLIBCURL_LINKTYPE=static -DJAVA=false"
BUILD: "win_build"
@@ -81,15 +91,21 @@ gcc8-x86:
gcc5:
image: docker.slock.it/build-images/cmake:gcc5
- extends: .conanbuild
+ extends:
+ - .conanbuild
+ - .only_full
clang50:
image: docker.slock.it/build-images/cmake:clang50
- extends: .conanbuild
+ extends:
+ - .conanbuild
+ - .only_full
-clang10:
- image: docker.slock.it/build-images/cmake:clang10
- extends: .conanbuild
+clang11:
+ image: docker.slock.it/build-images/cmake:clang11
+ extends:
+ - .conanbuild
+ - .only_full
mac_os:
needs: []
@@ -118,6 +134,7 @@ mac_os:
docker:
stage: bindings
needs: []
+ extends: .only_full
tags:
- short-jobs
services:
@@ -157,6 +174,7 @@ test_qemu:
image: docker.io/zephyrprojectrtos/zephyr-build:v0.12
stage: test
needs: []
+ extends: .only_full
script:
- west init -m https://github.com/zephyrproject-rtos/zephyr --mr v2.0.0
- export ZEPHYR_BASE=/builds/in3/c/in3-core
diff --git a/c/docs/1_install.md b/c/docs/1_install.md
index 1d76e7176..f091f8176 100644
--- a/c/docs/1_install.md
+++ b/c/docs/1_install.md
@@ -32,7 +32,7 @@ Default-Value: `-DASMJS=OFF`
if true, the bitcoin verifiers will be build
-Default-Value: `-DBTC=OFF`
+Default-Value: `-DBTC=ON`
#### BUILD_DOC
@@ -63,6 +63,13 @@ Default-Value: `-DCODE_COVERAGE=OFF`
Default-Value: `-DCOLOR=ON`
+#### DEV_NO_INTRN_PTR
+
+ (*dev option*) if true the client will NOT include a void pointer (named internal) for use by devs)
+
+Default-Value: `-DDEV_NO_INTRN_PTR=ON`
+
+
#### ERR_MSG
if set human readable error messages will be inculded in th executable, otherwise only the error code is used. (saves about 19kB)
@@ -147,6 +154,13 @@ Default-Value: `-DIPFS=ON`
Default-Value: `-DJAVA=OFF`
+#### PAY_ETH
+
+ support for direct Eth-Payment
+
+Default-Value: `-DPAY_ETH=OFF`
+
+
#### PKG_CONFIG_EXECUTABLE
pkg-config executable
diff --git a/c/examples/build.sh b/c/examples/build.sh
index 4ceed5e05..49df759e9 100755
--- a/c/examples/build.sh
+++ b/c/examples/build.sh
@@ -13,11 +13,14 @@ if [ ! -d /usr/local/include/in3 ]; then
fi
# set the library path to use the local
- BUILDARGS="-L../../build/lib/ -I../../c/include"
+ BUILDARGS="-L../../build/lib/ -I../../c/include/ "
fi
-
# now build the examples build
for f in *.c;
- do gcc -std=c99 -o "${f%%.*}" $f $BUILDARGS -lin3 -D_POSIX_C_SOURCE=199309L
+ do
+ if [ "$f" == ledger_sign.c ]; then # skipping ledger_sign compilation as it requires specific dependencies
+ continue
+ fi
+ gcc -std=c99 -o "${f%%.*}" $f $BUILDARGS -lin3 -D_POSIX_C_SOURCE=199309L
done
diff --git a/c/examples/ledger_sign.c b/c/examples/ledger_sign.c
new file mode 100644
index 000000000..850538fd2
--- /dev/null
+++ b/c/examples/ledger_sign.c
@@ -0,0 +1,48 @@
+
+#include // the core client
+#include // functions for direct api-access
+#include // if included the verifier will automaticly be initialized.
+#include //to invoke ledger nano device for signing
+#include // logging functions
+#include
+#include
+
+static void send_tx_api(in3_t* in3);
+
+int main() {
+ // create new incubed client
+ uint8_t bip_path[5] = {44, 60, 0, 0, 0};
+ in3_t* in3 = in3_for_chain(ETH_CHAIN_ID_MAINNET);
+ in3_log_set_level(LOG_DEBUG);
+ // setting ledger nano s to be the default signer for incubed client
+ // it will cause the transaction or any msg to be sent to ledger nanos device for siging
+ eth_ledger_set_signer(in3, bip_path);
+
+ // send tx using API
+ send_tx_api(in3);
+
+ // cleanup client after usage
+ in3_free(in3);
+}
+
+void send_tx_api(in3_t* in3) {
+ // prepare parameters
+ address_t to, from;
+ hex_to_bytes("0xC51fBbe0a68a7cA8d33f14a660126Da2A2FAF8bf", -1, from, 20);
+ hex_to_bytes("0xd46e8dd67c5d32be8058bb8eb970870f07244567", -1, to, 20);
+
+ bytes_t* data = hex_to_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);
+}
diff --git a/c/include/in3.rs.h b/c/include/in3.rs.h
index fc87c0243..8eb23d120 100644
--- a/c/include/in3.rs.h
+++ b/c/include/in3.rs.h
@@ -1,10 +1,15 @@
// AUTO-GENERATED FILE
// See scripts/build_includeh.sh
#include "../src/core/client/context_internal.h"
+#include "../src/third-party/crypto/ecdsa.h"
+#include "../src/third-party/crypto/hasher.h"
+#include "../src/third-party/crypto/secp256k1.c"
+#include "../src/verifier/eth1/basic/signer-priv.h"
+#include "../src/verifier/eth1/basic/signer.h"
#include "in3/bytes.h"
#include "in3/client.h"
#include "in3/context.h"
#include "in3/error.h"
#include "in3/eth_api.h"
-#include "in3/in3_init.h"
#include "in3/in3_curl.h"
+#include "in3/in3_init.h"
diff --git a/c/include/in3/error.h b/c/include/in3/error.h
index e973f4d81..a1d9399c2 100644
--- a/c/include/in3/error.h
+++ b/c/include/in3/error.h
@@ -69,6 +69,7 @@ typedef enum {
IN3_WAITING = -16, /**< the process can not be finished since we are waiting for responses */
IN3_EIGNORE = -17, /**< Ignorable error */
IN3_EPAYMENT_REQUIRED = -18, /**< payment required */
+ IN3_ENODEVICE = -19, /**< harware wallet device not connected */
} in3_ret_t;
/** Optional type similar to C++ std::optional
diff --git a/c/include/in3/ledger_signer.h b/c/include/in3/ledger_signer.h
new file mode 100644
index 000000000..548385094
--- /dev/null
+++ b/c/include/in3/ledger_signer.h
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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 .
+ *******************************************************************************/
+
+// @PUBLIC_HEADER
+/** @file
+ * this file defines the incubed configuration struct and it registration.
+ *
+ *
+ * */
+
+#ifndef in3_ledger_signer_h__
+#define in3_ledger_signer_h__
+
+#include "client.h"
+
+in3_ret_t eth_ledger_set_signer(in3_t* in3, uint8_t* bip_path);
+
+#endif
diff --git a/c/include/in3/signer.h b/c/include/in3/signer.h
index 1a3a4c68d..65c6ad061 100644
--- a/c/include/in3/signer.h
+++ b/c/include/in3/signer.h
@@ -49,4 +49,9 @@
*/
in3_ret_t eth_set_pk_signer(in3_t* in3, bytes32_t pk);
+/**
+ * simply signer with one private key as hex.
+ */
+uint8_t* eth_set_pk_signer_hex(in3_t* in3, char* key);
+
#endif
diff --git a/c/src/api/CMakeLists.txt b/c/src/api/CMakeLists.txt
index 361a0c819..337625915 100644
--- a/c/src/api/CMakeLists.txt
+++ b/c/src/api/CMakeLists.txt
@@ -39,6 +39,7 @@ IF (IN3API)
add_subdirectory(eth1)
add_subdirectory(usn)
+
IF (IPFS)
add_subdirectory(ipfs)
diff --git a/c/src/api/eth1/ens.c b/c/src/api/eth1/ens.c
index 1fc7b019d..44dc6caa9 100644
--- a/c/src/api/eth1/ens.c
+++ b/c/src/api/eth1/ens.c
@@ -130,6 +130,7 @@ in3_ret_t ens_resolve(in3_ctx_t* parent, char* name, const address_t registry, i
} else
switch (parent->client->chain_id) {
case ETH_CHAIN_ID_MAINNET:
+ case ETH_CHAIN_ID_GOERLI:
registry_address = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
break;
default:
diff --git a/c/src/api/eth1/eth_api.c b/c/src/api/eth1/eth_api.c
index 26a27c1c5..cf3b99354 100644
--- a/c/src/api/eth1/eth_api.c
+++ b/c/src/api/eth1/eth_api.c
@@ -543,8 +543,11 @@ uint64_t eth_estimate_fn(in3_t* in3, address_t contract, eth_blknum_t block, cha
va_start(ap, fn_sig);
uint64_t* response = eth_call_fn_intern(in3, contract, block, true, fn_sig, ap);
va_end(ap);
- uint64_t tmp = *response;
- _free(response);
+ uint64_t tmp = response ? *response : 0;
+ if (response)
+ _free(response);
+ else
+ api_set_error(ENOMEM, "No response!");
return tmp;
}
diff --git a/c/src/cmd/in3/CMakeLists.txt b/c/src/cmd/in3/CMakeLists.txt
index 43d7b00e2..2efbea5b8 100644
--- a/c/src/cmd/in3/CMakeLists.txt
+++ b/c/src/cmd/in3/CMakeLists.txt
@@ -60,7 +60,12 @@ endif()
add_executable(in3 main.c in3_storage.c)
target_compile_definitions(in3 PRIVATE _XOPEN_SOURCE=600)
-target_link_libraries(in3 ${LIBS} eth_full ${IN3_API} -lm)
+
+if( LEDGER_NANO AND HIDAPI)
+ target_link_libraries(in3 ${LIBS} eth_full ${IN3_API} ledger_signer -lm)
+else()
+ target_link_libraries(in3 ${LIBS} eth_full ${IN3_API} -lm)
+endif()
install(TARGETS in3
DESTINATION /usr/local/bin/
diff --git a/c/src/cmd/in3/main.c b/c/src/cmd/in3/main.c
index 518f014ee..8e4375c21 100644
--- a/c/src/cmd/in3/main.c
+++ b/c/src/cmd/in3/main.c
@@ -35,7 +35,6 @@
/** @file
* simple commandline-util sending in3-requests.
* */
-
#include "../../api/eth1/abi.h"
#include "../../api/eth1/eth_api.h"
#include "../../core/util/bitset.h"
@@ -60,6 +59,11 @@
#include "../../core/client/nodelist.h"
#include "../../core/client/version.h"
#include "../../core/util/colors.h"
+
+#if defined(LEDGER_NANO)
+#include "../../signer/ledger-nano/signer/ledger_signer.h"
+#endif
+
#include "../../verifier/eth1/basic/signer.h"
#include "../../verifier/eth1/evm/evm.h"
#include "../../verifier/eth1/full/eth_full.h"
@@ -108,6 +112,7 @@ void show_help(char* name) {
-d, -data the data for a transaction. This can be a filepath, a 0x-hexvalue or - for stdin.\n\
-gas the gas limit to use when sending transactions. (default: 100000) \n\
-pk the private key as raw as keystorefile \n\
+-bip32 the bip32 path which is to be used for signing in hardware wallet \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\
@@ -615,6 +620,9 @@ int main(int argc, char* argv[]) {
params[1] = 0;
int p = 1, i;
bytes32_t pk;
+#ifdef LEDGER_NANO
+ uint8_t bip32[5];
+#endif
// we want to verify all
in3_register_eth_full();
@@ -683,9 +691,19 @@ int main(int argc, char* argv[]) {
if (strcmp(argv[i], "-pk") == 0) { // private key?
if (argv[i + 1][0] == '0' && argv[i + 1][1] == 'x') {
hex_to_bytes(argv[++i], -1, pk, 32);
+
eth_set_pk_signer(c, pk);
} else
pk_file = argv[++i];
+ } else if (strcmp(argv[i], "-bip32") == 0) {
+#if defined(LEDGER_NANO)
+ if (argv[i + 1][0] == '0' && argv[i + 1][1] == 'x') {
+ hex_to_bytes(argv[++i], -1, bip32, 5);
+ eth_ledger_set_signer(c, bip32);
+ }
+#else
+ die("bip32 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
@@ -958,7 +976,7 @@ int main(int argc, char* argv[]) {
sig_type = "raw";
}
- if (!c->signer) die("No private key given");
+ if (!c->signer) die("No private key/bip32 path given");
uint8_t sig[65];
in3_ctx_t ctx;
ctx.client = c;
diff --git a/c/src/core/client/client.c b/c/src/core/client/client.c
index 4499c50a4..df62815c6 100644
--- a/c/src/core/client/client.c
+++ b/c/src/core/client/client.c
@@ -213,6 +213,31 @@ in3_signer_t* in3_create_signer(
return signer;
}
+/**
+ * set the transport handler on the client.
+ */
+void in3_set_transport(
+ in3_t* c, /**< the incubed client */
+ void* cptr /**< custom pointer which will will be passed to functions */
+) {
+ c->transport = cptr;
+}
+
+/**
+ * set the signer on the client.
+ * the caller will need to free this pointer after usage.
+ */
+in3_signer_t* in3_set_signer(
+ in3_t* c, /**< the incubed client */
+ in3_sign sign, /**< function pointer returning a stored value for the given key.*/
+ in3_prepare_tx prepare_tx, /**< function pointer returning capable of manipulating the transaction before signing it. This is needed in order to support multisigs.*/
+ void* wallet /**signer = signer;
+ return signer;
+}
+
in3_storage_handler_t* in3_set_storage_handler(
in3_t* c, /**< the incubed client */
in3_storage_get_item get_item, /**< function pointer returning a stored value for the given key.*/
diff --git a/c/src/core/client/client_init.c b/c/src/core/client/client_init.c
index 044e7cdc3..142d45c97 100644
--- a/c/src/core/client/client_init.c
+++ b/c/src/core/client/client_init.c
@@ -88,7 +88,7 @@ void in3_register_payment(
#define EXPECT_CFG(cond, err) EXPECT(cond, { \
res = malloc(strlen(err) + 1); \
- strcpy(res, err); \
+ if (res) strcpy(res, err); \
goto cleanup; \
})
#define EXPECT_CFG_NCP_ERR(cond, err) EXPECT(cond, { res = err; goto cleanup; })
@@ -587,7 +587,7 @@ char* in3_get_config(in3_t* c) {
if (c->replace_latest_block)
add_uint(sb, ',', "replaceLatestBlock", c->replace_latest_block);
add_uint(sb, ',', "requestCount", c->request_count);
- if (c->chain_id == ETH_CHAIN_ID_LOCAL)
+ if (c->chain_id == ETH_CHAIN_ID_LOCAL && chain)
add_string(sb, ',', "rpc", chain->nodelist->url);
sb_add_chars(sb, ",\"nodes\":{");
@@ -683,6 +683,7 @@ char* in3_configure(in3_t* c, const char* config) {
} else if (token->key == key("maxVerifiedHashes")) {
EXPECT_TOK_U16(token);
in3_chain_t* chain = in3_find_chain(c, c->chain_id);
+ EXPECT_CFG(chain, "chain not found");
if (c->max_verified_hashes < d_long(token)) {
chain->verified_hashes = _realloc(chain->verified_hashes,
sizeof(in3_verified_hash_t) * d_long(token),
diff --git a/c/src/core/client/execute.c b/c/src/core/client/execute.c
index 739c4f730..a97226085 100644
--- a/c/src/core/client/execute.c
+++ b/c/src/core/client/execute.c
@@ -576,7 +576,7 @@ static bool ctx_is_allowed_to_fail(in3_ctx_t* ctx) {
}
in3_ret_t ctx_handle_failable(in3_ctx_t* ctx) {
- ctx_remove_required(ctx, ctx->required);
+ in3_ret_t res = IN3_OK;
// blacklist node that gave us an error response for nodelist (if not first update)
// and clear nodelist params
@@ -587,11 +587,16 @@ in3_ret_t ctx_handle_failable(in3_ctx_t* ctx) {
_free(chain->nodelist_upd8_params);
chain->nodelist_upd8_params = NULL;
- // if first update return error otherwise return IN3_OK, this is because first update is
- // always from a boot node which is presumed to be trusted
- if (nodelist_first_upd8(chain))
- return ctx_set_error(ctx, ctx->required->error ? ctx->required->error : "error handling subrequest", IN3_ERPC);
- return IN3_OK;
+ if (ctx->required) {
+ // if first update return error otherwise return IN3_OK, this is because first update is
+ // always from a boot node which is presumed to be trusted
+ if (nodelist_first_upd8(chain))
+ res = ctx_set_error(ctx, ctx->required->error ? ctx->required->error : "error handling subrequest", IN3_ERPC);
+
+ if (res == IN3_OK) res = ctx_remove_required(ctx, ctx->required);
+ }
+
+ return res;
}
in3_ret_t in3_send_ctx(in3_ctx_t* ctx) {
@@ -657,7 +662,7 @@ in3_ret_t in3_send_ctx(in3_ctx_t* ctx) {
sb_add_range(&ctx->raw_response->result, (char*) sig, 0, 65);
break;
} else
- return ctx_set_error(ctx, "no transport set", IN3_ECONFIG);
+ return ctx_set_error(ctx, "no signer set", IN3_ECONFIG);
}
}
}
diff --git a/c/src/core/util/data.c b/c/src/core/util/data.c
index f3c7574d1..696c402d6 100644
--- a/c/src/core/util/data.c
+++ b/c/src/core/util/data.c
@@ -964,3 +964,7 @@ d_token_t* d_getl(d_token_t* item, uint16_t k, uint32_t minl) {
d_get_byteskl(item, k, minl);
return d_get(item, k);
}
+
+d_iterator_t d_iter(d_token_t* parent) {
+ return (d_iterator_t){.left = d_len(parent), .token = parent + 1};
+} /**< creates a iterator for a object or array */
diff --git a/c/src/core/util/data.h b/c/src/core/util/data.h
index 6039c43c4..d8b302d6d 100644
--- a/c/src/core/util/data.h
+++ b/c/src/core/util/data.h
@@ -104,19 +104,22 @@ typedef struct json_parser {
* Objects or arrays will return 0x.
*/
bytes_t d_to_bytes(d_token_t* item);
-int d_bytes_to(d_token_t* item, uint8_t* dst, const int max); /**< writes the byte-representation to the dst. details see d_to_bytes.*/
-bytes_t* d_bytes(const d_token_t* item); /**< returns the value as bytes (Carefully, make sure that the token is a bytes-type!)*/
-bytes_t* d_bytesl(d_token_t* item, size_t l); /**< returns the value as bytes with length l (may reallocates) */
-char* d_string(const d_token_t* item); /**< converts the value as string. Make sure the type is string! */
-int32_t d_int(const d_token_t* item); /**< returns the value as integer. only if type is integer */
-int32_t d_intd(const d_token_t* item, const uint32_t def_val); /**< returns the value as integer or if NULL the default. only if type is integer */
-uint64_t d_long(const d_token_t* item); /**< returns the value as long. only if type is integer or bytes, but short enough */
-uint64_t d_longd(const d_token_t* item, const uint64_t def_val); /**< returns the value as long or if NULL the default. only if type is integer or bytes, but short enough */
-bytes_t** d_create_bytes_vec(const d_token_t* arr); /** creates a array of bytes from JOSN-array */
-static inline d_type_t d_type(const d_token_t* item) { return item == NULL ? T_NULL : (item->len & 0xF0000000) >> 28; } /**< type of the token */
-static inline int d_len(const d_token_t* item) { return item == NULL ? 0 : item->len & 0xFFFFFFF; } /**< number of elements in the token (only for object or array, other will return 0) */
-bool d_eq(const d_token_t* a, const d_token_t* b); /**< compares 2 token and if the value is equal */
-d_key_t keyn(const char* c, const size_t len); /**< generates the keyhash for the given stringrange as defined by len */
+int d_bytes_to(d_token_t* item, uint8_t* dst, const int max); /**< writes the byte-representation to the dst. details see d_to_bytes.*/
+bytes_t* d_bytes(const d_token_t* item); /**< returns the value as bytes (Carefully, make sure that the token is a bytes-type!)*/
+bytes_t* d_bytesl(d_token_t* item, size_t l); /**< returns the value as bytes with length l (may reallocates) */
+char* d_string(const d_token_t* item); /**< converts the value as string. Make sure the type is string! */
+int32_t d_int(const d_token_t* item); /**< returns the value as integer. only if type is integer */
+int32_t d_intd(const d_token_t* item, const uint32_t def_val); /**< returns the value as integer or if NULL the default. only if type is integer */
+uint64_t d_long(const d_token_t* item); /**< returns the value as long. only if type is integer or bytes, but short enough */
+uint64_t d_longd(const d_token_t* item, const uint64_t def_val); /**< returns the value as long or if NULL the default. only if type is integer or bytes, but short enough */
+bytes_t** d_create_bytes_vec(const d_token_t* arr); /** creates a array of bytes from JOSN-array */
+static inline d_type_t d_type(const d_token_t* item) { return (item ? ((item->len & 0xF0000000) >> 28) : T_NULL); } /**< type of the token */
+static inline int d_len(const d_token_t* item) { /**< number of elements in the token (only for object or array, other will return 0) */
+ if (item == NULL) return 0;
+ return item->len & 0xFFFFFFF;
+}
+bool d_eq(const d_token_t* a, const d_token_t* b); /**< compares 2 token and if the value is equal */
+d_key_t keyn(const char* c, const size_t len); /**< generates the keyhash for the given stringrange as defined by len */
d_token_t* d_get(d_token_t* item, const uint16_t key); /**< returns the token with the given propertyname (only if item is a object) */
d_token_t* d_get_or(d_token_t* item, const uint16_t key1, const uint16_t key2); /**< returns the token with the given propertyname or if not found, tries the other. (only if item is a object) */
@@ -191,8 +194,8 @@ typedef struct d_iterator {
int left; /**< number of result left */
} d_iterator_t;
-static inline d_iterator_t d_iter(d_token_t* parent) { return (d_iterator_t){.left = d_len(parent), .token = parent + 1}; } /**< creates a iterator for a object or array */
-static inline bool d_iter_next(d_iterator_t* const iter) {
+d_iterator_t d_iter(d_token_t* parent); /**< creates a iterator for a object or array */
+static inline bool d_iter_next(d_iterator_t* const iter) {
iter->token = d_next(iter->token);
return iter->left--;
} /**< fetched the next token an returns a boolean indicating whther there is a next or not.*/
diff --git a/c/src/core/util/debug.c b/c/src/core/util/debug.c
index 991293341..de001adaa 100644
--- a/c/src/core/util/debug.c
+++ b/c/src/core/util/debug.c
@@ -98,6 +98,7 @@ char* in3_errmsg(in3_ret_t err /**< the error code */) {
case IN3_WAITING: return "waiting for data";
case IN3_EIGNORE: return "ignoreable error";
case IN3_EPAYMENT_REQUIRED: return "payment required";
+ case IN3_ENODEVICE: return "no hardware wallet connected";
}
return NULL;
#else
diff --git a/c/src/core/util/error.h b/c/src/core/util/error.h
index e973f4d81..a1d9399c2 100644
--- a/c/src/core/util/error.h
+++ b/c/src/core/util/error.h
@@ -69,6 +69,7 @@ typedef enum {
IN3_WAITING = -16, /**< the process can not be finished since we are waiting for responses */
IN3_EIGNORE = -17, /**< Ignorable error */
IN3_EPAYMENT_REQUIRED = -18, /**< payment required */
+ IN3_ENODEVICE = -19, /**< harware wallet device not connected */
} in3_ret_t;
/** Optional type similar to C++ std::optional
diff --git a/c/src/signer/ledger-nano/README.md b/c/src/signer/ledger-nano/README.md
new file mode 100644
index 000000000..314588937
--- /dev/null
+++ b/c/src/signer/ledger-nano/README.md
@@ -0,0 +1,85 @@
+# Integration of ledger nano s with incubed
+ 1. Setup development environment for ledger nano s
+ 2. Build and install ledger nano Signer app into Ledger nano s usb device
+ 3. Install libusb hidlib
+ 4. Start using ledger nano s device with Incubed
+
+# Setup development environment for ledger nano s
+ Setting up dev environment for Ledger nano s is one time activity and Signer application will be available to install directly from Ledger Manager in future. Ledger applications need linux System (recommended is Ubuntu) to build the binary to be installed on Ledger nano devices
+
+## Download Toolchains and Nanos ledger SDK (As per latest Ubuntu LTS)
+
+Download the Nano S SDK in bolos-sdk folder
+$ git clone https://github.com/ledgerhq/nanos-secure-sdk
+
+Download a prebuild gcc and move it to bolos-sdk folder
+ https://launchpad.net/gcc-arm-embedded/+milestone/5-2016-q1-update
+
+Download a prebuild clang and rename the folder to clang-arm-fropi then move it to bolos-sdk folder
+ http://releases.llvm.org/download.html#4.0.0
+
+
+## Add environment variables:
+
+sudo -H gedit /etc/environment
+
+ADD PATH TO BOLOS SDK:
+BOLOS_SDK="/nanos-secure-sdk"
+
+ADD GCCPATH VARIABLE
+GCCPATH="/gcc-arm-none-eabi-5_3-2016q1/bin/"
+
+ADD CLANGPATH
+CLANGPATH="/clang-arm-fropi/bin/"
+
+
+## Download and install ledger python tools
+
+Installation prerequisites :
+$ sudo apt-get install libudev-dev
+$ sudo apt-get install libusb-1.0-0-dev
+$ sudo apt-get install python-dev (python 2.7)
+$ sudo apt-get install virtualenv
+
+Installation of ledgerblue:
+$ virtualenv ledger
+$ source ledger/bin/activate
+$ pip install ledgerblue
+
+Ref: https://github.com/LedgerHQ/blue-loader-python
+
+
+
+## Download and install ledger udev rules
+
+$ git clone https://github.com/LedgerHQ/udev-rules
+
+run script from the above download
+$ sudo ./add_udev_rules.sh
+
+
+
+## Open new terminal and check for following installations :-
+
+$ sudo apt-get install gcc-multilib
+$ sudo apt-get install libc6-dev:i386
+
+===================================================================
+
+# Build and install ledger nano Signer app into Ledger nano s usb device
+Once the setup is done, go to ledger-incubed-firmware-app folder and run:-
+
+$ make
+$ make load
+
+===================================================================
+
+# Install libusb hidlib
+HIDAPI library is required to interact with ledger nano s device over usb , it is available for multiple platforms and can be cross compiled easily
+
+Ref: https://github.com/libusb/hidapi
+===================================================================
+
+# Start using ledger nano s device with Incubed
+
+Open the application on your ledger nano s usb device and make signing requests from incubed
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/firmware/Makefile b/c/src/signer/ledger-nano/firmware/Makefile
new file mode 100755
index 000000000..d63f8eaaa
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/Makefile
@@ -0,0 +1,86 @@
+#*******************************************************************************
+# Ledger Blue
+# (c) 2016 Ledger
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#*******************************************************************************
+
+
+
+ifeq ($(BOLOS_SDK),)
+$(error BOLOS_SDK is not set)
+endif
+include $(BOLOS_SDK)/Makefile.defines
+
+# Main app configuration
+
+APPNAME = "Incubed Signer"
+APPVERSION = 1.0.0
+APP_LOAD_PARAMS = --appFlags 0x00 $(COMMON_LOAD_PARAMS)
+
+# Build configuration
+
+APP_SOURCE_PATH += src
+SDK_SOURCE_PATH += lib_stusb lib_stusb_impl
+
+DEFINES += APPVERSION=\"$(APPVERSION)\"
+
+DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=128
+DEFINES += HAVE_BAGL HAVE_SPRINTF
+#DEFINES += PRINTF\(...\)=
+DEFINES += HAVE_SPRINTF HAVE_PRINTF PRINTF=screen_printf
+DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
+
+DEFINES += CX_COMPLIANCE_141
+
+# Compiler, assembler, and linker
+
+ifneq ($(BOLOS_ENV),)
+$(info BOLOS_ENV=$(BOLOS_ENV))
+CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/
+GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/
+else
+$(info BOLOS_ENV is not set: falling back to CLANGPATH and GCCPATH)
+endif
+
+ifeq ($(CLANGPATH),)
+$(info CLANGPATH is not set: clang will be used from PATH)
+endif
+
+ifeq ($(GCCPATH),)
+$(info GCCPATH is not set: arm-none-eabi-* will be used from PATH)
+endif
+
+CC := $(CLANGPATH)clang
+CFLAGS += -O3 -Os
+
+AS := $(GCCPATH)arm-none-eabi-gcc
+AFLAGS +=
+
+LD := $(GCCPATH)arm-none-eabi-gcc
+LDFLAGS += -O3 -Os
+LDLIBS += -lm -lgcc -lc
+
+# Main rules
+
+all: default
+
+load: all
+ python3 -m ledgerblue.loadApp $(APP_LOAD_PARAMS)
+
+delete:
+ python3 -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS)
+
+# Import generic rules from the SDK
+
+include $(BOLOS_SDK)/Makefile.rules
diff --git a/c/src/signer/ledger-nano/firmware/README.md b/c/src/signer/ledger-nano/firmware/README.md
new file mode 100644
index 000000000..88fec7aaf
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/README.md
@@ -0,0 +1,5 @@
+# Sample Signature App for Ledger Blue & Ledger Nano S
+
+
+
+Run `make load` to build and load the application onto the device.
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/firmware/src/apdu.c b/c/src/signer/ledger-nano/firmware/src/apdu.c
new file mode 100755
index 000000000..8d94e956c
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/apdu.c
@@ -0,0 +1,144 @@
+#include "apdu.h"
+
+#include "menu.h"
+#include "operations.h"
+#include "ui.h"
+#include
+#include
+#include
+
+ux_state_t ux;
+
+void main_loop(void) {
+ volatile unsigned int rx = 0;
+ volatile unsigned int tx = 0;
+ volatile unsigned int flags = 0;
+ int isequal;
+ char* ans;
+
+ // next timer callback in 500 ms
+ UX_CALLBACK_SET_INTERVAL(500);
+
+ // DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only
+ // goal is to retrieve APDU.
+ // When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make
+ // sure the io_event is called with a
+ // switch event, before the apdu is replied to the bootloader. This avoid
+ // APDU injection faults.
+ for (;;) {
+ volatile unsigned short sw = 0;
+
+ BEGIN_TRY {
+ TRY {
+ rx = tx;
+ tx = 0; // ensure no race in catch_other if io_exchange throws an error
+
+ rx = io_exchange(CHANNEL_APDU | flags, rx);
+ flags = 0;
+
+ // no apdu received, well, reset the session, and reset the
+ // bootloader configuration
+ if (rx == 0) {
+ THROW(EXC_SECURITY);
+ }
+
+ if (G_io_apdu_buffer[0] != CLA) {
+ THROW(EXC_CLASS);
+ }
+
+ switch (G_io_apdu_buffer[1]) {
+
+ case INS_SIGN: {
+
+ if ((G_io_apdu_buffer[2] != P1_MORE) &&
+ (G_io_apdu_buffer[2] != P1_LAST)) {
+ THROW(EXC_WRONG_PARAM_P1P2);
+ }
+
+ current_text_pos = 0;
+ text_y = 60;
+ cx_ecfp_public_key_t publicKey;
+ cx_ecfp_private_key_t privateKey;
+ cx_curve_t curve_id = curve_code_to_curve(G_io_apdu_buffer[3]);
+
+ if (G_io_apdu_buffer[4] != TAG_ARG1) {
+ THROW(EXC_WRONG_PARAM);
+ }
+
+ int path_length = G_io_apdu_buffer[5];
+ unsigned char bip32_path[path_length];
+ memcpy(bip32_path, G_io_apdu_buffer + 6, path_length);
+
+ publicKey = public_key_at_given_path(curve_id, bip32_path, path_length);
+
+ if (G_io_apdu_buffer[6 + path_length] != TAG_ARG2) {
+ THROW(EXC_WRONG_PARAM);
+ }
+
+ int hash_len = G_io_apdu_buffer[7 + path_length];
+ PRINTF(" hash length %d \n", hash_len);
+ if (hash_len != HASH_LEN) {
+ THROW(EXC_WRONG_PARAM);
+ }
+
+ memcpy(msg_hash, G_io_apdu_buffer + 8 + path_length, HASH_LEN);
+ PRINTF("msg hash copied %02x %02x %02x %02x\n", msg_hash[0], msg_hash[1], msg_hash[30], msg_hash[31]);
+
+ private_key_at_given_path(curve_id, bip32_path, path_length);
+
+ PRINTF("private key fetched\n");
+
+ display_text_part();
+ ui_text();
+ flags |= IO_ASYNCH_REPLY;
+ } break;
+
+ case INS_GET_PUBLIC_KEY: {
+
+ cx_ecfp_public_key_t publicKey;
+ cx_curve_t curve_id = curve_code_to_curve(G_io_apdu_buffer[3]);
+
+ int path_length = G_io_apdu_buffer[4];
+ unsigned char bip32_path[path_length];
+
+ memcpy(bip32_path, G_io_apdu_buffer + 5, path_length);
+
+ publicKey = public_key_at_given_path(curve_id, bip32_path, path_length);
+
+ os_memmove(G_io_apdu_buffer, publicKey.W, 65);
+ tx = 65;
+ THROW(EXC_NO_ERROR);
+ } break;
+
+ case 0xFF: // return to dashboard
+ goto return_to_dashboard;
+
+ default:
+ THROW(EXC_INVALID_INS);
+ break;
+ }
+ }
+ CATCH_OTHER(e) {
+ switch (e & 0xF000) {
+ case 0x6000:
+ case 0x9000:
+ sw = e;
+ break;
+ default:
+ sw = 0x6800 | (e & 0x7FF);
+ break;
+ }
+ // Unexpected exception => report
+ G_io_apdu_buffer[tx] = sw >> 8;
+ G_io_apdu_buffer[tx + 1] = sw;
+ tx += 2;
+ }
+ FINALLY {
+ }
+ }
+ END_TRY;
+ }
+
+return_to_dashboard:
+ return;
+}
diff --git a/c/src/signer/ledger-nano/firmware/src/apdu.h b/c/src/signer/ledger-nano/firmware/src/apdu.h
new file mode 100755
index 000000000..af777ce65
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/apdu.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "globals.h"
+
+#define CLA 0x80
+#define INS_SIGN 0x02
+#define INS_GET_PUBLIC_KEY 0x04
+
+
+#define TAG_ARG1 0X01
+#define TAG_ARG2 0X02
+
+#define P1_LAST 0x80
+#define P1_MORE 0x00
+
+void main_loop();
diff --git a/c/src/signer/ledger-nano/firmware/src/error_codes.h b/c/src/signer/ledger-nano/firmware/src/error_codes.h
new file mode 100755
index 000000000..57318827b
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/error_codes.h
@@ -0,0 +1,4 @@
+#pragma once
+
+#define SUCCESS 0
+#define WRONG_TAG_BYTE 1
diff --git a/c/src/signer/ledger-nano/firmware/src/exception.h b/c/src/signer/ledger-nano/firmware/src/exception.h
new file mode 100755
index 000000000..73f35561c
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/exception.h
@@ -0,0 +1,18 @@
+#pragma once
+
+// Throw this to indicate prompting
+#define ASYNC_EXCEPTION 0x2000
+#define EXC_WRONG_PARAM 0x6B00
+#define EXC_WRONG_PARAM_P1P2 0x6A86
+#define EXC_WRONG_LENGTH 0x6C00
+#define EXC_INVALID_INS 0x6D00
+#define EXC_WRONG_LENGTH_FOR_INS 0x917E
+#define EXC_REJECT 0x6985
+#define EXC_PARSE_ERROR 0x9405
+#define EXC_WRONG_VALUES 0x6A80
+#define EXC_SECURITY 0x6982
+#define EXC_HID_REQUIRED 0x6983
+#define EXC_CLASS 0x6E00
+#define EXC_NO_ERROR 0x9000
+#define EXC_MEMORY_ERROR 0x9200
+#define EXC_NO_UUID_STORED 0x6988
diff --git a/c/src/signer/ledger-nano/firmware/src/globals.h b/c/src/signer/ledger-nano/firmware/src/globals.h
new file mode 100755
index 000000000..999e2557b
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/globals.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "os.h"
+#include "cx.h"
+#include
+#include "exception.h"
+#include "os_io_seproxyhal.h"
+#include
+#include
+#include "error_codes.h"
+
+// data stored in non volatile flash memory,prefix N_ is mandatory to store in flash
+extern WIDE nvram_data N_data_real;
+
+
+
+extern nvram_data new_data;
+
+
+#define N_data (*(WIDE nvram_data*)PIC(&N_data_real))
+
+
+
+extern unsigned int current_text_pos; // parsing cursor in the text to display
+extern unsigned int text_y; // current location of the displayed text
+extern cx_sha256_t hash;
+extern unsigned char msg_hash[HASH_LEN];
+extern cx_ecfp_private_key_t private_key;
+
+//bip32 path stored after apdu request parsing
+extern unsigned int path[BIP32_PATH_LEN_MAX];
+extern int path_len_bip;
+
+// ui currently displayed
+enum UI_STATE { UI_IDLE, UI_TEXT, UI_APPROVAL };
+
+extern enum UI_STATE uiState;
+
+extern char lineBuffer[100];
diff --git a/c/src/signer/ledger-nano/firmware/src/glyphs.h b/c/src/signer/ledger-nano/firmware/src/glyphs.h
new file mode 100644
index 000000000..e69de29bb
diff --git a/c/src/signer/ledger-nano/firmware/src/main.c b/c/src/signer/ledger-nano/firmware/src/main.c
new file mode 100755
index 000000000..ad07ecb60
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/main.c
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Ledger Blue
+ * (c) 2016 Ledger
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ********************************************************************************/
+#include "apdu.h"
+#include "globals.h"
+#include "menu.h"
+#include "ui.h"
+
+unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
+
+__attribute__((section(".boot"))) int main(void) {
+ // exit critical section
+ __asm volatile("cpsie i");
+
+ current_text_pos = 0;
+ text_y = 60;
+ // hashTainted = 1;
+ uiState = UI_IDLE;
+
+ // ensure exception will work as planned
+ os_boot();
+
+ UX_INIT();
+
+ BEGIN_TRY {
+ TRY {
+ io_seproxyhal_init();
+
+#ifdef LISTEN_BLE
+ if (os_seph_features() &
+ SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_BLE) {
+ BLE_power(0, NULL);
+ // restart IOs
+ BLE_power(1, NULL);
+ }
+#endif
+
+ USB_power(0);
+ USB_power(1);
+
+ ui_idle();
+
+ main_loop();
+ }
+ CATCH_OTHER(e) {
+ }
+ FINALLY {
+ }
+ }
+ END_TRY;
+}
diff --git a/c/src/signer/ledger-nano/firmware/src/menu.c b/c/src/signer/ledger-nano/firmware/src/menu.c
new file mode 100755
index 000000000..bf0f110d8
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/menu.c
@@ -0,0 +1,133 @@
+#include "menu.h"
+
+#include "operations.h"
+#include "ui.h"
+
+unsigned int current_text_pos; // parsing cursor in the text to display
+unsigned int text_y;
+enum UI_STATE uiState;
+char lineBuffer[100];
+
+unsigned char display_text_part() {
+ PRINTF("display_text_part: enter\n");
+ unsigned int i;
+
+ // WIDE char* text = (char*) G_io_apdu_buffer + 5;
+ // PRINTF("display_text_part: text pointer %d %d\n", G_io_apdu_buffer[4], current_text_pos);
+ // if (text[current_text_pos] == '\0') {
+ // PRINTF("display_text_part: returning null\n");
+ // return 0;
+ // }
+ // i = 0;
+ // while ((text[current_text_pos] != 0) && (text[current_text_pos] != '\n') &&
+ // (i < MAX_CHARS_PER_LINE)) {
+ // PRINTF("display_text_part: counter %d \n", current_text_pos);
+ // lineBuffer[i++] = text[current_text_pos];
+ // current_text_pos++;
+ // }
+ // if (text[current_text_pos] == '\n') {
+ // current_text_pos++;
+ // }
+ tohex(msg_hash, HASH_LEN, lineBuffer, sizeof(lineBuffer));
+ current_text_pos = HASH_LEN * 2;
+ lineBuffer[current_text_pos] = NULL;
+#ifdef TARGET_BLUE
+ os_memset(bagl_ui_text, 0, sizeof(bagl_ui_text));
+ bagl_ui_text[0].component.type = BAGL_LABEL;
+ bagl_ui_text[0].component.x = 4;
+ bagl_ui_text[0].component.y = text_y;
+ bagl_ui_text[0].component.width = 320;
+ bagl_ui_text[0].component.height = TEXT_HEIGHT;
+
+ bagl_ui_text[0].component.fgcolor = 0x000000;
+ bagl_ui_text[0].component.bgcolor = 0xf9f9f9;
+ bagl_ui_text[0].component.font_id = DEFAULT_FONT;
+ bagl_ui_text[0].text = lineBuffer;
+ text_y += TEXT_HEIGHT + TEXT_SPACE;
+#endif
+
+ PRINTF("display_text_part:exit");
+ return 0;
+}
+
+void ui_idle(void) {
+ uiState = UI_IDLE;
+#ifdef TARGET_BLUE
+ UX_DISPLAY(bagl_ui_idle_blue, NULL);
+#else
+ UX_DISPLAY(bagl_ui_idle_nanos, NULL);
+#endif
+}
+
+void ui_text(void) {
+ uiState = UI_TEXT;
+#ifdef TARGET_BLUE
+ UX_DISPLAY(bagl_ui_text, NULL);
+#else
+ UX_DISPLAY(bagl_ui_text_review_nanos, NULL);
+#endif
+}
+
+void ui_approval(void) {
+ uiState = UI_APPROVAL;
+#ifdef TARGET_BLUE
+ UX_DISPLAY(bagl_ui_approval_blue, NULL);
+#else
+ UX_DISPLAY(bagl_ui_approval_nanos, NULL);
+#endif
+}
+
+unsigned char io_event(unsigned char channel) {
+ // nothing done with the event, throw an error on the transport layer if
+ // needed
+
+ // can't have more than one tag in the reply, //PRINTF ("io_event:enter"); not supported yet.
+ switch (G_io_seproxyhal_spi_buffer[0]) {
+ case SEPROXYHAL_TAG_FINGER_EVENT:
+ UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
+ break;
+
+ case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: // for Nano S
+ UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
+ break;
+
+ case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
+ if ((uiState == UI_TEXT) &&
+ (os_seph_features() &
+ SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_BIG)) {
+ if (!display_text_part()) {
+ //PRINTF ("io_event:display_text_part");
+ ui_approval();
+ } else {
+ UX_REDISPLAY();
+ }
+ } else {
+ UX_DISPLAYED_EVENT();
+ }
+ break;
+
+ case SEPROXYHAL_TAG_TICKER_EVENT:
+#ifdef TARGET_NANOS
+ UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {
+ // defaulty retrig very soon (will be overriden during
+ // stepper_prepro)
+ UX_CALLBACK_SET_INTERVAL(500);
+ UX_REDISPLAY();
+ });
+#endif
+ break;
+
+ // unknown events are acknowledged
+ default:
+ UX_DEFAULT_EVENT();
+ break;
+ }
+
+ // close the event if not done previously (by a display or whatever)
+ if (!io_seproxyhal_spi_is_status_sent()) {
+ io_seproxyhal_general_status();
+ }
+
+ // command has been processed, DO NOT reset the current APDU transport
+ return 1;
+}
diff --git a/c/src/signer/ledger-nano/firmware/src/menu.h b/c/src/signer/ledger-nano/firmware/src/menu.h
new file mode 100755
index 000000000..4ff0bf390
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/menu.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "globals.h"
+
+unsigned char display_text_part();
+
+void ui_idle(void);
+
+void ui_text(void);
+
+void ui_approval(void);
+
+unsigned char io_event(unsigned char channel);
diff --git a/c/src/signer/ledger-nano/firmware/src/operations.c b/c/src/signer/ledger-nano/firmware/src/operations.c
new file mode 100755
index 000000000..93fddfa3f
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/operations.c
@@ -0,0 +1,178 @@
+#include "operations.h"
+
+#include "apdu.h"
+#include "menu.h"
+
+cx_sha256_t hash;
+unsigned int path[BIP32_PATH_LEN_MAX];
+int path_len_bip;
+unsigned char msg_hash[HASH_LEN];
+cx_ecfp_private_key_t private_key;
+
+//static const unsigned int path__[5]= {44|0x80000000, 60|0x80000000, 0|0x80000000, 0, 0};
+
+//function to get public key at the given path
+cx_ecfp_public_key_t public_key_at_given_path(cx_curve_t curve_id, unsigned char* loc, int path_len) {
+ PRINTF("public_key_at_given_path:enter");
+ cx_ecfp_public_key_t public_key;
+ cx_ecfp_private_key_t private_key;
+ unsigned char private_key_data[32];
+ path_len_bip = read_bip32_path(path_len, loc, path);
+
+ os_perso_derive_node_bip32(CX_CURVE_256K1, path, path_len_bip, private_key_data, NULL);
+
+ cx_ecdsa_init_private_key(CX_CURVE_256K1, private_key_data, 32, &private_key);
+
+ cx_ecfp_generate_pair(CX_CURVE_256K1, &public_key, &private_key, 1);
+
+ PRINTF("public_key_at_given_path:exit");
+ return public_key;
+}
+
+//function to get private key at the given path
+cx_ecfp_private_key_t private_key_at_given_path(cx_curve_t curve_id, unsigned char* loc, int path_len) {
+ cx_ecfp_public_key_t public_key;
+ unsigned char private_key_data[32];
+ path_len_bip = read_bip32_path(path_len, loc, path);
+ os_perso_derive_node_bip32(CX_CURVE_256K1, path, path_len_bip, private_key_data, NULL);
+ cx_ecdsa_init_private_key(CX_CURVE_256K1, private_key_data, 32, &private_key);
+ cx_ecfp_generate_pair(CX_CURVE_256K1, &public_key, &private_key, 1);
+ return private_key;
+}
+
+const bagl_element_t* io_seproxyhal_touch_exit(const bagl_element_t* e) {
+ // Go back to the dashboard
+ os_sched_exit(0);
+ return NULL; // do not redraw the widget
+}
+
+const bagl_element_t*
+io_seproxyhal_touch_approve(const bagl_element_t* e) {
+ unsigned int tx = 0;
+ cx_curve_t curve_id = curve_code_to_curve(G_io_apdu_buffer[3]);
+
+ if (G_io_apdu_buffer[2] == P1_LAST) {
+
+ unsigned char result[32];
+ os_memmove(result, msg_hash, HASH_LEN);
+ PRINTF("msg hash signed %02x %02x %02x %02x\n", result[0], result[1], result[30], result[31]);
+ tx = cx_ecdsa_sign((void*) &private_key, CX_RND_RFC6979 | CX_LAST, CX_KECCAK, result,
+ sizeof(result), G_io_apdu_buffer, NULL);
+
+ G_io_apdu_buffer[0] &= 0xF0; // discard the parity information
+ }
+ G_io_apdu_buffer[tx++] = 0x90;
+ G_io_apdu_buffer[tx++] = 0x00;
+ // Send back the response, do not restart the event loop
+ io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
+ // Display back the original UX
+ ui_idle();
+ return 0; // do not redraw the widget
+}
+
+const bagl_element_t* io_seproxyhal_touch_deny(const bagl_element_t* e) {
+
+ G_io_apdu_buffer[0] = 0x69;
+ G_io_apdu_buffer[1] = 0x85;
+ // Send back the response, do not restart the event loop
+ io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
+ // Display back the original UX
+ ui_idle();
+ return 0; // do not redraw the widget
+}
+
+unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
+ switch (channel & ~(IO_FLAGS)) {
+ case CHANNEL_KEYBOARD:
+ break;
+
+ // multiplexed io exchange over a SPI channel and TLV encapsulated protocol
+ case CHANNEL_SPI:
+ if (tx_len) {
+ io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
+
+ if (channel & IO_RESET_AFTER_REPLIED) {
+ reset();
+ }
+ return 0; // nothing received from the master so far (it's a tx
+ // transaction)
+ } else {
+ return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
+ }
+
+ default:
+ THROW(EXC_WRONG_PARAM);
+ }
+ return 0;
+}
+
+void io_seproxyhal_display(const bagl_element_t* element) {
+ io_seproxyhal_display_default((bagl_element_t*) element);
+}
+
+uint8_t curve_to_curve_code(cx_curve_t curve) {
+ switch (curve) {
+ case CX_CURVE_Ed25519:
+ return IDM_ED;
+ case CX_CURVE_SECP256K1:
+ return IDM_SECP256K1;
+ case CX_CURVE_SECP256R1:
+ return IDM_SECP256R1;
+ default:
+ THROW(EXC_MEMORY_ERROR);
+ }
+}
+
+cx_curve_t curve_code_to_curve(uint8_t curve_code) {
+ static const cx_curve_t curves[] = {CX_CURVE_Ed25519, CX_CURVE_SECP256K1, CX_CURVE_SECP256R1};
+ if (curve_code > sizeof(curves) / sizeof(*curves)) {
+ THROW(EXC_WRONG_PARAM);
+ }
+ return curves[curve_code];
+}
+
+int generate_hash(unsigned char* data, int data_len, unsigned char* out_hash) {
+ PRINTF("generate_hash:enter");
+ PRINTF("generate_hash: data len %d %d %d\n", data_len, data[0], data[data_len - 1]);
+ PRINTF("generate_hash: hash %u hash.header %u out_hash %u\n", hash, hash.header, out_hash);
+ cx_sha256_init(&hash);
+ cx_hash(&hash.header, 0, data, data_len, NULL);
+ int size = cx_hash(&hash.header, CX_LAST, data, 0, out_hash);
+ PRINTF("\ngenerate_hash: out_hash %d %d \n", out_hash[0], out_hash[HASH_LEN - 1]);
+ PRINTF("generate_hash:exit");
+ return size;
+}
+
+uint32_t read_bip32_path(uint32_t bytes, const uint8_t* buf, uint32_t* bip32_path) {
+ uint32_t path_length = bytes;
+ PRINTF(" bytes %d path_length %d ", bytes, path_length);
+
+ for (size_t i = 0; i < path_length; i++) {
+ //PRINTF("\n buf %d bip32_path %d path__ %d i %d",buf[i],bip32_path[i],path__[i], i);
+ if (i < 3)
+ bip32_path[i] = buf[i] | (0x80000000);
+ else
+ bip32_path[i] = buf[i] | (0x00000000);
+
+ //PRINTF("\n buf %d bip32_path %d path__ %d i %d \n",buf[i],bip32_path[i],path__[i], i);
+ }
+
+ return path_length;
+}
+
+void tohex(unsigned char* in, size_t insz, char* out, size_t outsz) {
+ unsigned char* pin = in;
+ const char* hex = "0123456789ABCDEF";
+ char* pout = out;
+ for (; pin < in + insz; pout += 3, pin++) {
+ pout[0] = hex[(*pin >> 4) & 0xF];
+ pout[1] = hex[*pin & 0xF];
+
+ if (pout + 2 - out > outsz) {
+ /* Better to truncate output string than overflow buffer */
+ /* it would be still better to either return a status */
+ /* or ensure the target buffer is large enough and it never happen */
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/firmware/src/operations.h b/c/src/signer/ledger-nano/firmware/src/operations.h
new file mode 100755
index 000000000..be44a8419
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/operations.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "globals.h"
+
+cx_ecfp_private_key_t private_key_at_given_path(cx_curve_t curve_id, unsigned char* loc, int path_len);
+
+cx_ecfp_public_key_t public_key_at_given_path(cx_curve_t curve_id, unsigned char* loc, int path_len);
+
+const bagl_element_t* io_seproxyhal_touch_exit(const bagl_element_t* e);
+
+const bagl_element_t* io_seproxyhal_touch_approve(const bagl_element_t* e);
+
+const bagl_element_t* io_seproxyhal_touch_deny(const bagl_element_t* e);
+
+unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len);
+
+void io_seproxyhal_display(const bagl_element_t* element);
+
+uint8_t curve_to_curve_code(cx_curve_t curve);
+
+cx_curve_t curve_code_to_curve(uint8_t curve_code);
+
+int generate_hash(unsigned char* data, int data_len, unsigned char* out_hash);
+
+uint32_t read_bip32_path(uint32_t bytes, const uint8_t* buf, uint32_t* bip32_path);
+
+void tohex(unsigned char* in, size_t insz, char* out, size_t outsz);
diff --git a/c/src/signer/ledger-nano/firmware/src/types.h b/c/src/signer/ledger-nano/firmware/src/types.h
new file mode 100755
index 000000000..faf8bc500
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/types.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#define CX_CURVE_256K1 CX_CURVE_SECP256K1
+#define HASH_LEN 0x20
+#define BIP32_PATH_LEN_MAX 0x14
+#define MAX_CHARS_PER_LINE 49
+#define DEFAULT_FONT BAGL_FONT_OPEN_SANS_LIGHT_16px | BAGL_FONT_ALIGNMENT_LEFT
+#define TEXT_HEIGHT 15
+#define TEXT_SPACE 4
+
+typedef unsigned char uchar_t;
+
+typedef enum MODULES {
+ SIGN = 1,
+ GET_PUBLIC_KEY = 2,
+} MODULES;
+
+typedef enum {
+ IDM_ED = 0,
+ IDM_SECP256K1 = 1,
+ IDM_SECP256R1 = 2,
+ IDM_NO_CURVE = 255,
+} curve_code;
+
+typedef struct {
+ cx_curve_t curve;
+ uint8_t path_length;
+ uint32_t bip32_path[BIP32_PATH_LEN_MAX];
+} nvram_data;
diff --git a/c/src/signer/ledger-nano/firmware/src/ui.c b/c/src/signer/ledger-nano/firmware/src/ui.c
new file mode 100755
index 000000000..f85b99e44
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/ui.c
@@ -0,0 +1,69 @@
+#include "ui.h"
+
+#include "menu.h"
+#include "operations.h"
+
+unsigned int
+bagl_ui_approval_blue_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ return 0;
+}
+
+unsigned int
+bagl_ui_idle_blue_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ return 0;
+}
+
+unsigned int
+bagl_ui_text_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ return 0;
+}
+
+unsigned int
+bagl_ui_idle_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ switch (button_mask) {
+ case BUTTON_EVT_RELEASED | BUTTON_LEFT:
+ case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT:
+ io_seproxyhal_touch_exit(NULL);
+ break;
+ }
+
+ return 0;
+}
+
+unsigned int
+bagl_ui_approval_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ switch (button_mask) {
+ case BUTTON_EVT_RELEASED | BUTTON_RIGHT:
+ io_seproxyhal_touch_approve(NULL);
+ break;
+
+ case BUTTON_EVT_RELEASED | BUTTON_LEFT:
+ io_seproxyhal_touch_deny(NULL);
+ break;
+ }
+ return 0;
+}
+
+unsigned int
+bagl_ui_text_review_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter) {
+ switch (button_mask) {
+ case BUTTON_EVT_RELEASED | BUTTON_RIGHT:
+ if (!display_text_part()) {
+ ui_approval();
+ } else {
+ UX_REDISPLAY();
+ }
+ break;
+
+ case BUTTON_EVT_RELEASED | BUTTON_LEFT:
+ io_seproxyhal_touch_deny(NULL);
+ break;
+ }
+ return 0;
+}
diff --git a/c/src/signer/ledger-nano/firmware/src/ui.h b/c/src/signer/ledger-nano/firmware/src/ui.h
new file mode 100755
index 000000000..9f3dacc64
--- /dev/null
+++ b/c/src/signer/ledger-nano/firmware/src/ui.h
@@ -0,0 +1,254 @@
+#pragma once
+
+#include "globals.h"
+
+#ifdef TARGET_BLUE
+
+// UI to approve or deny the signature proposal
+static const bagl_element_t const bagl_ui_approval_blue[] = {
+
+ {
+ {BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 190, 215, 120, 40, 0, 6,
+ BAGL_FILL, 0x41ccb4, 0xF9F9F9, BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
+ "Deny",
+ 0,
+ 0x37ae99,
+ 0xF9F9F9,
+ io_seproxyhal_touch_deny,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 190, 265, 120, 40, 0, 6,
+ BAGL_FILL, 0x41ccb4, 0xF9F9F9, BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
+ "Approve",
+ 0,
+ 0x37ae99,
+ 0xF9F9F9,
+ io_seproxyhal_touch_approve,
+ NULL,
+ NULL,
+ },
+};
+
+unsigned int
+bagl_ui_approval_blue_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+
+// UI displayed when no signature proposal has been received
+static const bagl_element_t bagl_ui_idle_blue[] = {
+
+ {
+ {BAGL_RECTANGLE, 0x00, 0, 60, 320, 420, 0, 0, BAGL_FILL, 0xf9f9f9,
+ 0xf9f9f9, 0, 0},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_RECTANGLE, 0x00, 0, 0, 320, 60, 0, 0, BAGL_FILL, 0x1d2028,
+ 0x1d2028, 0, 0},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_LABEL, 0x00, 20, 0, 320, 60, 0, 0, BAGL_FILL, 0xFFFFFF, 0x1d2028,
+ BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
+ "Sample Sign",
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_BUTTON | BAGL_FLAG_TOUCHABLE, 0x00, 190, 215, 120, 40, 0, 6,
+ BAGL_FILL, 0x41ccb4, 0xF9F9F9, BAGL_FONT_OPEN_SANS_LIGHT_14px | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE, 0},
+ "Exit",
+ 0,
+ 0x37ae99,
+ 0xF9F9F9,
+ io_seproxyhal_touch_exit,
+ NULL,
+ NULL,
+ },
+};
+
+unsigned int
+bagl_ui_idle_blue_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+
+static bagl_element_t bagl_ui_text[1];
+
+unsigned int
+bagl_ui_text_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+
+#else
+
+static const bagl_element_t bagl_ui_idle_nanos[] = {
+
+ {
+ {BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000,
+ 0xFFFFFF, 0, 0},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_LABELINE, 0x02, 0, 12, 128, 11, 0, 0, 0, 0xFFFFFF, 0x000000,
+ BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
+ "Waiting for message",
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
+ BAGL_GLYPH_ICON_CROSS},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+};
+
+unsigned int
+bagl_ui_idle_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+
+static const bagl_element_t bagl_ui_approval_nanos[] = {
+
+ {
+ {BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000,
+ 0xFFFFFF, 0, 0},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_LABELINE, 0x02, 0, 12, 128, 11, 0, 0, 0, 0xFFFFFF, 0x000000,
+ BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
+ "Sign message",
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
+ BAGL_GLYPH_ICON_CROSS},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
+ BAGL_GLYPH_ICON_CHECK},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+};
+
+unsigned int
+bagl_ui_approval_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+
+static const bagl_element_t bagl_ui_text_review_nanos[] = {
+
+ {
+ {BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000,
+ 0xFFFFFF, 0, 0},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_LABELINE, 0x02, 0, 12, 128, 11, 0, 0, 0, 0xFFFFFF, 0x000000,
+ BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
+ "Verify text",
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_LABELINE, 0x02, 23, 26, 82, 11, 0x80 | 10, 0, 0, 0xFFFFFF,
+ 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 26},
+ lineBuffer,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
+ BAGL_GLYPH_ICON_CROSS},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
+ BAGL_GLYPH_ICON_CHECK},
+ NULL,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ },
+};
+
+unsigned int
+bagl_ui_text_review_nanos_button(unsigned int button_mask,
+ unsigned int button_mask_counter);
+#endif
diff --git a/c/src/signer/ledger-nano/signer/CMakeLists.txt b/c/src/signer/ledger-nano/signer/CMakeLists.txt
new file mode 100644
index 000000000..1c050216b
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/CMakeLists.txt
@@ -0,0 +1,59 @@
+###############################################################################
+# 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 .
+###############################################################################
+#cmake_minimum_required(VERSION 3.15)
+include("${PROJECT_SOURCE_DIR}/c/compiler.cmake")
+
+if(UNIX AND NOT APPLE)
+ set(LINUX TRUE)
+endif()
+
+add_library(ledger_signer_o OBJECT ledger_signer.c device_apdu_commands.c)
+target_compile_definitions(ledger_signer_o PRIVATE -D_POSIX_C_SOURCE=199309L)
+add_library(ledger_signer STATIC $)
+
+
+if(APPLE)
+ target_link_libraries(ledger_signer ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_SHARED_LIBRARY_PREFIX}hidapi${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBS})
+elseif(LINUX)
+ target_link_libraries(ledger_signer ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libhidapi-hidraw${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBS})
+elseif(WIN32)
+ # not building for windows currently
+ # target_link_libraries(ledger_signer ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_SHARED_LIBRARY_PREFIX}hidapi${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBS})
+else()
+ target_link_libraries(ledger_signer ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libhidapi-hidraw${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBS})
+endif()
+
+if(NOT WIN32)
+ add_dependencies(ledger_signer lib-hidapi)
+endif()
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/signer/device_apdu_commands.c b/c/src/signer/ledger-nano/signer/device_apdu_commands.c
new file mode 100644
index 000000000..5e20e4bcf
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/device_apdu_commands.c
@@ -0,0 +1,77 @@
+#ifdef WIN32
+#include
+#endif
+
+#include "../../../core/util/log.h"
+#include "../../../third-party/hidapi/hidapi/hidapi.h"
+#include "device_apdu_commands.h"
+#include
+#include
+#include
+
+static uint8_t CHANNEL[] = {0x01, 0x01};
+
+const uint8_t CLA = 0x80;
+const uint8_t INS_GET_PUBLIC_KEY = 0x04;
+const uint8_t INS_SIGN = 0x02;
+const uint8_t P1_MORE = 0x00;
+const uint8_t P1_FINAL = 0X80;
+const uint8_t P2_FINAL = 0X00;
+const uint8_t TAG = 0x05;
+
+void wrap_apdu(bytes_t i_apdu, uint16_t seq, bytes_t* o_wrapped_hid_cmd) {
+
+ uint16_t apdu_len = (uint16_t) i_apdu.len;
+ uint8_t data[2];
+ int index = 0;
+ uint8_t cmd[HID_CMD_MAX_LEN];
+
+ memset(cmd + index, 0x00, sizeof(cmd));
+
+ memcpy(cmd + index, CHANNEL, sizeof(CHANNEL));
+ index += sizeof(CHANNEL);
+
+ memcpy(cmd + index, &TAG, 1);
+ index += 1;
+
+ len_to_bytes(seq, data);
+ in3_log_debug("data[0] %d data[1] %d\n", data[0], data[1]);
+ memcpy(cmd + index, data, sizeof(data));
+ index += sizeof(data);
+
+ len_to_bytes(apdu_len, data);
+ in3_log_debug("data[0] %d data[1] %d\n", data[0], data[1]);
+ memcpy(cmd + index, data, sizeof(data));
+ index += sizeof(data);
+
+ memcpy(cmd + index, i_apdu.data, i_apdu.len);
+
+ o_wrapped_hid_cmd->len = HID_CMD_MAX_LEN;
+ o_wrapped_hid_cmd->data = malloc(HID_CMD_MAX_LEN);
+
+ memcpy(o_wrapped_hid_cmd->data, cmd, HID_CMD_MAX_LEN);
+}
+
+void unwrap_apdu(bytes_t i_wrapped_hid_cmd, bytes_t* o_apdu_res) {
+ uint8_t buf[2];
+ buf[0] = i_wrapped_hid_cmd.data[5];
+ buf[1] = i_wrapped_hid_cmd.data[6];
+
+ int len = bytes_to_len(buf);
+
+ o_apdu_res->len = len;
+ o_apdu_res->data = malloc(len);
+ memcpy(o_apdu_res->data, len, i_wrapped_hid_cmd.data + 7);
+}
+
+int len_to_bytes(uint16_t x, uint8_t* buf) {
+
+ buf[1] = (uint8_t)(x & 0xFF);
+ buf[0] = (uint8_t)((x >> 8) & 0xFF);
+ return 2;
+}
+
+uint16_t bytes_to_len(uint8_t* buf) {
+ uint16_t number = (buf[1] << 8) + buf[0];
+ return number;
+}
diff --git a/c/src/signer/ledger-nano/signer/device_apdu_commands.h b/c/src/signer/ledger-nano/signer/device_apdu_commands.h
new file mode 100644
index 000000000..346e38b8e
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/device_apdu_commands.h
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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_device_apdu_h__
+#define in3_device_apdu_h__
+
+#include "../../../core/client/client.h"
+#define HID_CMD_MAX_LEN 64
+
+extern const uint8_t CLA;
+extern const uint8_t INS_GET_PUBLIC_KEY;
+extern const uint8_t INS_SIGN;
+extern const uint8_t P1_MORE;
+extern const uint8_t P1_FINAL;
+extern const uint8_t P2_FINAL;
+extern const uint8_t TAG;
+
+int len_to_bytes(uint16_t x, uint8_t* buf);
+
+uint16_t bytes_to_len(uint8_t* buf);
+
+void wrap_apdu(bytes_t i_apdu, uint16_t seq, bytes_t* o_wrapped_hid_cmd);
+
+void unwrap_apdu(bytes_t o_wrapped_hid_cmd, bytes_t* o_apdu_res);
+
+#endif
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/signer/ledger_signer.c b/c/src/signer/ledger-nano/signer/ledger_signer.c
new file mode 100644
index 000000000..a7ce879c1
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/ledger_signer.c
@@ -0,0 +1,316 @@
+#ifdef WIN32
+#include
+#endif
+
+#include "../../../core/client/context.h"
+#include "../../../core/util/bytes.h"
+#include "../../../core/util/log.h"
+#include "device_apdu_commands.h"
+#include "ledger_signer.h"
+#include "ledger_signer_priv.h"
+
+#include
+#include
+#include
+
+#define MAX_STR 255
+
+in3_ret_t is_ledger_device_connected() {
+ int res = 0;
+ in3_ret_t ret;
+ wchar_t wstr[MAX_STR];
+
+ res = hid_init();
+ hid_device* handle;
+
+ handle = hid_open(LEDGER_NANOS_VID, LEDGER_NANOS_PID, NULL);
+
+ if (NULL != handle) {
+ in3_log_info("device connected \n");
+
+ res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
+ in3_log_debug("device manufacturer: %ls\n", wstr);
+
+ hid_get_product_string(handle, wstr, MAX_STR);
+ in3_log_debug("product: %ls\n", wstr);
+
+ ret = IN3_OK;
+ } else {
+ ret = IN3_ENODEVICE;
+ }
+
+ hid_close(handle);
+ res = hid_exit();
+
+ return ret;
+}
+
+in3_ret_t eth_get_address_from_path(bytes_t i_bip_path, bytes_t o_address) {
+ //not implemented currently
+ return IN3_EUNKNOWN;
+}
+
+in3_ret_t eth_ledger_sign(void* ctx, d_signature_type_t type, bytes_t message, bytes_t account, uint8_t* dst) {
+ //UNUSED_VAR(account); // at least for now
+ uint8_t* bip_path_bytes = ((in3_ctx_t*) ctx)->client->signer->wallet;
+
+ uint8_t bip_data[5];
+
+ int res = 0;
+ in3_ret_t ret;
+
+ hid_device* handle;
+ uint8_t apdu[64];
+ uint8_t buf[2];
+ int index_counter = 0;
+ uint8_t bytes_read = 0;
+
+ uint8_t msg_len = 32;
+ uint8_t hash[32];
+ uint8_t read_buf[255];
+
+ bool is_hashed = false;
+ bytes_t apdu_bytes;
+ bytes_t final_apdu_command;
+ uint8_t public_key[65];
+ bytes_t response;
+
+ memcpy(bip_data, bip_path_bytes, sizeof(bip_data));
+
+ ret = eth_ledger_get_public_key(bip_data, public_key);
+ res = hid_init();
+ handle = hid_open(LEDGER_NANOS_VID, LEDGER_NANOS_PID, NULL);
+ int cmd_size = 64;
+ int recid = 0;
+
+ if (NULL != handle) {
+
+ hid_set_nonblocking(handle, 0);
+
+ switch (type) {
+ case SIGN_EC_RAW:
+ memcpy(hash, message.data, message.len);
+ is_hashed = true;
+ case SIGN_EC_HASH:
+ if (!is_hashed)
+ hasher_Raw(HASHER_SHA3K, message.data, message.len, hash);
+
+ apdu[index_counter++] = CLA;
+ apdu[index_counter++] = INS_SIGN;
+ apdu[index_counter++] = P1_FINAL;
+ apdu[index_counter++] = IDM_SECP256K1;
+
+ apdu[index_counter++] = 0x01; //1st arg tag
+ apdu[index_counter++] = sizeof(bip_data);
+ memcpy(apdu + index_counter, &bip_data, sizeof(bip_data));
+ index_counter += sizeof(bip_data);
+
+ apdu[index_counter++] = 0x02; //2nd arg tag
+ apdu[index_counter++] = msg_len;
+ memcpy(apdu + index_counter, hash, msg_len);
+ index_counter += msg_len;
+
+ apdu_bytes.data = malloc(index_counter);
+ apdu_bytes.len = index_counter;
+ memcpy(apdu_bytes.data, apdu, index_counter);
+
+ wrap_apdu(apdu_bytes, 0, &final_apdu_command);
+
+#ifdef DEBUG
+ in3_log_debug("apdu commnd sent to device\n");
+ ba_print(final_apdu_command.data, final_apdu_command.len);
+#endif
+
+ res = hid_write(handle, final_apdu_command.data, final_apdu_command.len);
+
+ in3_log_debug("written to hid %d\n", res);
+
+ read_hid_response(handle, &response);
+
+#ifdef DEBUG
+ in3_log_debug("response received from device\n");
+ ba_print(response.data, response.len);
+#endif
+
+ if (response.data[response.len - 2] == 0x90 && response.data[response.len - 1] == 0x00) {
+ ret = IN3_OK;
+
+ in3_log_debug("apdu executed succesfully \n");
+ extract_signture(response, dst);
+ recid = get_recid_from_pub_key(&secp256k1, public_key, dst, hash);
+ dst[64] = recid;
+
+#ifdef DEBUG
+ in3_log_debug("printing signature returned by device with recid value\n");
+ ba_print(dst, 65);
+#endif
+
+ } else {
+ in3_log_fatal("error in apdu execution \n");
+ ret = IN3_ENOTSUP;
+ }
+
+ free(final_apdu_command.data);
+ free(apdu_bytes.data);
+ ret = IN3_OK;
+ break;
+
+ default:
+ return IN3_ENOTSUP;
+ }
+
+ } else {
+ in3_log_fatal("no ledger device connected \n");
+ ret = IN3_ENODEVICE;
+ }
+ hid_close(handle);
+ res = hid_exit();
+ return 65;
+}
+
+in3_ret_t eth_ledger_get_public_key(uint8_t* i_bip_path, uint8_t* o_public_key) {
+ int res = 0;
+ in3_ret_t ret;
+ uint8_t apdu[64];
+ uint8_t buf[2];
+ int index_counter = 0;
+ uint16_t msg_len = 0;
+ uint8_t bytes_read = 0;
+
+ bytes_t apdu_bytes;
+ bytes_t final_apdu_command;
+ bytes_t response;
+ hid_device* handle;
+
+ res = hid_init();
+ handle = hid_open(LEDGER_NANOS_VID, LEDGER_NANOS_PID, NULL);
+ if (NULL != handle) {
+ apdu[index_counter++] = CLA;
+ apdu[index_counter++] = INS_GET_PUBLIC_KEY;
+ apdu[index_counter++] = P1_FINAL;
+ apdu[index_counter++] = IDM_SECP256K1;
+
+ apdu[index_counter++] = 5;
+ memcpy(apdu + index_counter, i_bip_path, 5);
+ index_counter += 5;
+
+ apdu_bytes.data = malloc(index_counter);
+ apdu_bytes.len = index_counter;
+ memcpy(apdu_bytes.data, apdu, index_counter);
+
+ wrap_apdu(apdu_bytes, 0, &final_apdu_command);
+
+ res = hid_write(handle, final_apdu_command.data, final_apdu_command.len);
+
+ read_hid_response(handle, &response);
+
+#ifdef DEBUG
+ in3_log_debug("response received from device\n");
+ ba_print(response.data, response.len);
+#endif
+
+ if (response.data[response.len - 2] == 0x90 && response.data[response.len - 1] == 0x00) {
+ ret = IN3_OK;
+ memcpy(o_public_key, response.data, response.len - 2);
+ } else {
+ ret = IN3_ENOTSUP;
+ }
+ free(final_apdu_command.data);
+ free(apdu_bytes.data);
+ free(response.data);
+
+ } else {
+ ret = IN3_ENODEVICE;
+ }
+ hid_close(handle);
+ res = hid_exit();
+ return ret;
+}
+
+in3_ret_t eth_ledger_set_signer(in3_t* in3, uint8_t* bip_path) {
+ if (in3->signer) free(in3->signer);
+ in3->signer = malloc(sizeof(in3_signer_t));
+ in3->signer->sign = eth_ledger_sign;
+ in3->signer->prepare_tx = NULL;
+ in3->signer->wallet = bip_path;
+ return IN3_OK;
+}
+
+void extract_signture(bytes_t i_raw_sig, uint8_t* o_sig) {
+
+ //ECDSA signature encoded as TLV: 30 L 02 Lr r 02 Ls s
+ int lr = i_raw_sig.data[3];
+ int ls = i_raw_sig.data[lr + 5];
+ int offset = 0;
+ in3_log_debug("lr %d, ls %d \n", lr, ls);
+ if (lr > 0x20) {
+ memcpy(o_sig + offset, i_raw_sig.data + 5, lr - 1);
+ offset = lr - 1;
+ } else {
+ memcpy(o_sig, i_raw_sig.data + 4, lr);
+ offset = lr;
+ }
+
+ if (ls > 0x20) {
+ memcpy(o_sig + offset, i_raw_sig.data + lr + 7, ls - 1);
+ } else {
+ memcpy(o_sig + offset, i_raw_sig.data + lr + 6, ls);
+ }
+}
+
+void read_hid_response(hid_device* handle, bytes_t* response) {
+ uint8_t read_chunk[64];
+ uint8_t read_buf[255];
+ int index_counter = 0;
+ int bytes_to_read = 0;
+ int total_bytes_available = 0;
+ int bytes_read = 0;
+ do {
+ bytes_read = hid_read(handle, read_chunk, sizeof(read_chunk));
+
+ if (bytes_read > 0) {
+
+ if (index_counter == 0) //first chunk read
+ {
+ total_bytes_available = read_chunk[6];
+ index_counter += (bytes_read - 7);
+
+ memcpy(read_buf, read_chunk + 7, bytes_read - 7);
+ } else {
+ memcpy(read_buf + index_counter, read_chunk + 5, total_bytes_available - index_counter);
+ index_counter += (bytes_read - 5);
+ }
+ bytes_to_read = total_bytes_available - index_counter;
+ }
+ if (bytes_to_read <= 0) {
+ break;
+ }
+
+ } while (bytes_read > 0);
+
+ response->len = total_bytes_available;
+ response->data = malloc(total_bytes_available);
+ memcpy(response->data, read_buf, total_bytes_available);
+}
+
+int get_recid_from_pub_key(const ecdsa_curve* curve, uint8_t* pub_key, const uint8_t* sig, const uint8_t* digest) {
+
+ int i = 0;
+ uint8_t p_key[65];
+ int ret = 0;
+ int recid = -1;
+ for (i = 0; i < 4; i++) {
+ ret = ecdsa_recover_pub_from_sig(curve, p_key, sig, digest, i);
+ if (ret == 0) {
+ if (memcmp(pub_key, p_key, 65) == 0) {
+ recid = i;
+#ifdef DEBUG
+ in3_log_debug("public key matched with recid value\n");
+ ba_print(p_key, 65, "get_recid_from_pub_key :keys matched");
+#endif
+ break;
+ }
+ }
+ }
+ return recid;
+}
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/signer/ledger_signer.h b/c/src/signer/ledger-nano/signer/ledger_signer.h
new file mode 100644
index 000000000..89e720e8b
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/ledger_signer.h
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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 .
+ *******************************************************************************/
+
+// @PUBLIC_HEADER
+/** @file
+ * this file defines the incubed configuration struct and it registration.
+ *
+ *
+ * */
+
+#ifndef in3_ledger_signer_h__
+#define in3_ledger_signer_h__
+
+#include "../../../core/client/client.h"
+
+in3_ret_t eth_ledger_set_signer(in3_t* in3, uint8_t* bip_path);
+in3_ret_t eth_ledger_get_public_key(uint8_t* i_bip_path, uint8_t* o_public_key);
+in3_ret_t eth_ledger_sign(void* ctx, d_signature_type_t type, bytes_t message, bytes_t account, uint8_t* dst);
+
+#endif
\ No newline at end of file
diff --git a/c/src/signer/ledger-nano/signer/ledger_signer_priv.h b/c/src/signer/ledger-nano/signer/ledger_signer_priv.h
new file mode 100644
index 000000000..008c6bbe2
--- /dev/null
+++ b/c/src/signer/ledger-nano/signer/ledger_signer_priv.h
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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_ledger_signer_priv_h__
+#define in3_ledger_signer_priv_h__
+
+#include "../../../core/client/client.h"
+#include "../../../third-party/crypto/ecdsa.h"
+#include "../../../third-party/crypto/secp256k1.h"
+#include "../../../third-party/hidapi/hidapi/hidapi.h"
+
+#define LEDGER_NANOS_VID 0x2C97
+#define LEDGER_NANOS_PID 0x1001
+
+typedef enum CURVE_CODE_ {
+ IDM_ED = 0,
+ IDM_SECP256K1 = 1,
+ IDM_SECP256R1 = 2,
+ IDM_NO_CURVE = 255,
+} CURVE_CODE;
+
+void extract_signture(bytes_t i_raw_sig, uint8_t* o_sig);
+void read_hid_response(hid_device* handle, bytes_t* response);
+int get_recid_from_pub_key(const ecdsa_curve* curve, uint8_t* pub_key, const uint8_t* sig, const uint8_t* digest);
+in3_ret_t is_ledger_device_connected();
+
+in3_ret_t eth_get_address_from_path(bytes_t i_bip_path, bytes_t o_address);
+
+#endif
\ No newline at end of file
diff --git a/c/src/third-party/CMakeLists.txt b/c/src/third-party/CMakeLists.txt
index a0c111730..a93da3eb2 100644
--- a/c/src/third-party/CMakeLists.txt
+++ b/c/src/third-party/CMakeLists.txt
@@ -47,3 +47,7 @@ endif()
if (IPFS)
add_subdirectory( libb64 )
endif()
+
+if (HIDAPI)
+ add_subdirectory( hidapi )
+endif()
diff --git a/c/src/third-party/hidapi/.appveyor.yml b/c/src/third-party/hidapi/.appveyor.yml
new file mode 100644
index 000000000..b7e21c764
--- /dev/null
+++ b/c/src/third-party/hidapi/.appveyor.yml
@@ -0,0 +1,33 @@
+os: Visual Studio 2015
+
+environment:
+ matrix:
+ - BUILD_ENV: msbuild
+ arch: x64
+ - BUILD_ENV: msbuild
+ arch: Win32
+ - BUILD_ENV: cygwin
+
+install:
+ - cmd: if %BUILD_ENV%==cygwin (
+ C:\cygwin64\setup-x86_64.exe --quiet-mode --no-shortcuts --upgrade-also --packages autoconf,automake )
+
+build_script:
+ - cmd: if %BUILD_ENV%==msbuild (
+ msbuild .\windows\hidapi.sln /p:Configuration=Release /p:Platform=%arch% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" )
+ - cmd: if %BUILD_ENV%==cygwin (
+ C:\cygwin64\bin\bash -exlc "cd $APPVEYOR_BUILD_FOLDER; ./bootstrap; ./configure; make" )
+
+artifacts:
+ # Win32 artifacts
+ - path: .\windows\Release\hidapi.dll
+ - path: .\windows\Release\hidapi.lib
+ - path: .\windows\Release\hidapi.pdb
+ - path: .\windows\Release\hidtest.exe
+ - path: .\windows\Release\hidtest.pdb
+ # x64 artifacts
+ - path: .\windows\x64\Release\hidapi.dll
+ - path: .\windows\x64\Release\hidapi.lib
+ - path: .\windows\x64\Release\hidapi.pdb
+ - path: .\windows\x64\Release\hidtest.exe
+ - path: .\windows\x64\Release\hidtest.pdb
diff --git a/c/src/third-party/hidapi/.builds/alpine.yml b/c/src/third-party/hidapi/.builds/alpine.yml
new file mode 100644
index 000000000..9477671aa
--- /dev/null
+++ b/c/src/third-party/hidapi/.builds/alpine.yml
@@ -0,0 +1,25 @@
+image: alpine/edge
+packages:
+- autoconf
+- automake
+- libtool
+- eudev-dev
+- libusb-dev
+- linux-headers
+sources:
+- https://github.com/libusb/hidapi
+tasks:
+- setup: |
+ cd hidapi
+ ./bootstrap
+ ./configure
+- build: |
+ cd hidapi
+ make
+ make DESTDIR=$PWD/root install
+ make clean
+- build-manual: |
+ cd hidapi/linux
+ make -f Makefile-manual
+ cd ../libusb
+ make -f Makefile-manual
diff --git a/c/src/third-party/hidapi/.builds/archlinux.yml b/c/src/third-party/hidapi/.builds/archlinux.yml
new file mode 100644
index 000000000..e98996d42
--- /dev/null
+++ b/c/src/third-party/hidapi/.builds/archlinux.yml
@@ -0,0 +1,18 @@
+image: archlinux
+sources:
+- https://github.com/libusb/hidapi
+tasks:
+- setup: |
+ cd hidapi
+ ./bootstrap
+ ./configure
+- build: |
+ cd hidapi
+ make
+ make DESTDIR=$PWD/root install
+ make clean
+- build-manual: |
+ cd hidapi/linux
+ make -f Makefile-manual
+ cd ../libusb
+ make -f Makefile-manual
diff --git a/c/src/third-party/hidapi/.builds/fedora-mingw.yml b/c/src/third-party/hidapi/.builds/fedora-mingw.yml
new file mode 100644
index 000000000..4effecf32
--- /dev/null
+++ b/c/src/third-party/hidapi/.builds/fedora-mingw.yml
@@ -0,0 +1,22 @@
+image: fedora/latest
+packages:
+- autoconf
+- automake
+- libtool
+- mingw64-gcc
+- mingw64-gcc-c++
+sources:
+- https://github.com/libusb/hidapi
+tasks:
+- setup: |
+ cd hidapi
+ ./bootstrap
+ mingw64-configure
+- build: |
+ cd hidapi
+ make
+ make DESTDIR=$PWD/root install
+ make clean
+- build-manual: |
+ cd hidapi/windows
+ make -f Makefile-manual OS=MINGW CC=x86_64-w64-mingw32-gcc
diff --git a/c/src/third-party/hidapi/.builds/freebsd.yml b/c/src/third-party/hidapi/.builds/freebsd.yml
new file mode 100644
index 000000000..355dc4930
--- /dev/null
+++ b/c/src/third-party/hidapi/.builds/freebsd.yml
@@ -0,0 +1,23 @@
+image: freebsd/latest
+packages:
+- autoconf
+- automake
+- gmake
+- libiconv
+- libtool
+- pkgconf
+sources:
+- https://github.com/libusb/hidapi
+tasks:
+- setup: |
+ cd hidapi
+ ./bootstrap
+ ./configure
+- build: |
+ cd hidapi
+ make
+ make DESTDIR=$PWD/root install
+ make clean
+- build-manual: |
+ cd hidapi/libusb
+ gmake -f Makefile-manual
diff --git a/c/src/third-party/hidapi/.cirrus.yml b/c/src/third-party/hidapi/.cirrus.yml
new file mode 100644
index 000000000..b4cf20166
--- /dev/null
+++ b/c/src/third-party/hidapi/.cirrus.yml
@@ -0,0 +1,33 @@
+alpine_task:
+ container:
+ image: alpine:latest
+ install_script: apk add autoconf automake g++ gcc libusb-dev libtool linux-headers eudev-dev make musl-dev
+ script:
+ - ./bootstrap
+ - ./configure || { cat config.log; exit 1; }
+ - make
+ - make install
+
+freebsd11_task:
+ freebsd_instance:
+ image: freebsd-11-2-release-amd64
+ install_script:
+ - pkg install -y
+ autoconf automake libiconv libtool pkgconf
+ script:
+ - ./bootstrap
+ - ./configure || { cat config.log; exit 1; }
+ - make
+ - make install
+
+freebsd12_task:
+ freebsd_instance:
+ image: freebsd-12-1-release-amd64
+ install_script:
+ - pkg install -y
+ autoconf automake libiconv libtool pkgconf
+ script:
+ - ./bootstrap
+ - ./configure || { cat config.log; exit 1; }
+ - make
+ - make install
diff --git a/c/src/third-party/hidapi/.gitattributes b/c/src/third-party/hidapi/.gitattributes
new file mode 100644
index 000000000..edb79febc
--- /dev/null
+++ b/c/src/third-party/hidapi/.gitattributes
@@ -0,0 +1,7 @@
+* text=auto
+
+*.sln text eol=crlf
+*.vcproj text eol=crlf
+
+bootstrap text eol=lf
+configure.ac text eol=lf
diff --git a/c/src/third-party/hidapi/.gitignore b/c/src/third-party/hidapi/.gitignore
new file mode 100644
index 000000000..8438c4b81
--- /dev/null
+++ b/c/src/third-party/hidapi/.gitignore
@@ -0,0 +1,22 @@
+
+# Autotools-added generated files
+Makefile.in
+aclocal.m4
+ar-lib
+autom4te.cache/
+config.*
+configure
+compile
+depcomp
+install-sh
+libusb/Makefile.in
+linux/Makefile.in
+ltmain.sh
+mac/Makefile.in
+missing
+testgui/Makefile.in
+windows/Makefile.in
+
+Makefile
+stamp-h1
+libtool
diff --git a/c/src/third-party/hidapi/.travis.yml b/c/src/third-party/hidapi/.travis.yml
new file mode 100644
index 000000000..80367e94c
--- /dev/null
+++ b/c/src/third-party/hidapi/.travis.yml
@@ -0,0 +1,13 @@
+language: c
+
+os: osx
+osx_image: xcode10.2
+
+script:
+ - ./bootstrap
+ - ./configure
+ - make
+ - make DESTDIR=$PWD/root install
+ - make clean
+ - cd mac
+ - make -f Makefile-manual
diff --git a/c/src/third-party/hidapi/AUTHORS.txt b/c/src/third-party/hidapi/AUTHORS.txt
new file mode 100644
index 000000000..e08cb1619
--- /dev/null
+++ b/c/src/third-party/hidapi/AUTHORS.txt
@@ -0,0 +1,18 @@
+
+HIDAPI Authors:
+
+Alan Ott :
+ Original Author and Maintainer
+ Linux, Windows, and Mac implementations
+
+Ludovic Rousseau :
+ Formatting for Doxygen documentation
+ Bug fixes
+ Correctness fixes
+
+libusb/hidapi Team:
+ Development/maintainance since June 4th 2019
+
+For a comprehensive list of contributions, see the commit list at github:
+ https://github.com/libusb/hidapi/commits/master
+
diff --git a/c/src/third-party/hidapi/CMakeLists.txt b/c/src/third-party/hidapi/CMakeLists.txt
new file mode 100644
index 000000000..f5d08535e
--- /dev/null
+++ b/c/src/third-party/hidapi/CMakeLists.txt
@@ -0,0 +1,48 @@
+###############################################################################
+# 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 .
+###############################################################################
+
+include(ExternalProject)
+set(HIDAPI_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(HIDAPI_BIN ${CMAKE_CURRENT_BINARY_DIR})
+
+
+ExternalProject_Add(
+ lib-hidapi
+ SOURCE_DIR ${HIDAPI_DIR}/hidapi
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND cd ${HIDAPI_DIR} && ./bootstrap && ./configure --srcdir=${HIDAPI_DIR} --prefix=${CMAKE_BINARY_DIR}
+ BUILD_COMMAND cd ${HIDAPI_DIR} && make
+ INSTALL_COMMAND cd ${HIDAPI_DIR} && make install
+)
+
diff --git a/c/src/third-party/hidapi/HACKING.txt b/c/src/third-party/hidapi/HACKING.txt
new file mode 100644
index 000000000..761d4b655
--- /dev/null
+++ b/c/src/third-party/hidapi/HACKING.txt
@@ -0,0 +1,15 @@
+This file is mostly for the maintainer.
+
+1. Build hidapi.dll
+2. Build hidtest.exe in DEBUG and RELEASE
+3. Commit all
+
+4. Run the Following
+ export VERSION=0.1.0
+ export TAG_NAME=hidapi-$VERSION
+ git tag $TAG_NAME
+ git archive --format zip --prefix $TAG_NAME/ $TAG_NAME >../$TAG_NAME.zip
+5. Test the zip file.
+6. Run the following:
+ git push origin $TAG_NAME
+
diff --git a/c/src/third-party/hidapi/LICENSE-bsd.txt b/c/src/third-party/hidapi/LICENSE-bsd.txt
new file mode 100644
index 000000000..538cdf95c
--- /dev/null
+++ b/c/src/third-party/hidapi/LICENSE-bsd.txt
@@ -0,0 +1,26 @@
+Copyright (c) 2010, Alan Ott, Signal 11 Software
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Signal 11 Software nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/c/src/third-party/hidapi/LICENSE-gpl3.txt b/c/src/third-party/hidapi/LICENSE-gpl3.txt
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/c/src/third-party/hidapi/LICENSE-gpl3.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/c/src/third-party/hidapi/LICENSE-orig.txt b/c/src/third-party/hidapi/LICENSE-orig.txt
new file mode 100644
index 000000000..e3f338082
--- /dev/null
+++ b/c/src/third-party/hidapi/LICENSE-orig.txt
@@ -0,0 +1,9 @@
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Copyright 2009, Alan Ott, Signal 11 Software.
+ All Rights Reserved.
+
+ This software may be used by anyone for any reason so
+ long as the copyright notice in the source files
+ remains intact.
diff --git a/c/src/third-party/hidapi/LICENSE.txt b/c/src/third-party/hidapi/LICENSE.txt
new file mode 100644
index 000000000..e1676d4c4
--- /dev/null
+++ b/c/src/third-party/hidapi/LICENSE.txt
@@ -0,0 +1,13 @@
+HIDAPI can be used under one of three licenses.
+
+1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt
+2. A BSD-Style License, in LICENSE-bsd.txt.
+3. The more liberal original HIDAPI license. LICENSE-orig.txt
+
+The license chosen is at the discretion of the user of HIDAPI. For example:
+1. An author of GPL software would likely use HIDAPI under the terms of the
+GPL.
+
+2. An author of commercial closed-source software would likely use HIDAPI
+under the terms of the BSD-style license or the original HIDAPI license.
+
diff --git a/c/src/third-party/hidapi/Makefile.am b/c/src/third-party/hidapi/Makefile.am
new file mode 100644
index 000000000..00bcb73cf
--- /dev/null
+++ b/c/src/third-party/hidapi/Makefile.am
@@ -0,0 +1,85 @@
+
+ACLOCAL_AMFLAGS = -I m4
+
+if OS_FREEBSD
+pkgconfigdir=$(prefix)/libdata/pkgconfig
+else
+pkgconfigdir=$(libdir)/pkgconfig
+endif
+
+if OS_LINUX
+pkgconfig_DATA=pc/hidapi-hidraw.pc pc/hidapi-libusb.pc
+else
+pkgconfig_DATA=pc/hidapi.pc
+endif
+
+SUBDIRS=
+
+if OS_LINUX
+SUBDIRS += linux libusb
+endif
+
+if OS_DARWIN
+SUBDIRS += mac
+endif
+
+if OS_FREEBSD
+SUBDIRS += libusb
+endif
+
+if OS_KFREEBSD
+SUBDIRS += libusb
+endif
+
+if OS_HAIKU
+SUBDIRS += libusb
+endif
+
+if OS_WINDOWS
+SUBDIRS += windows
+endif
+
+SUBDIRS += hidtest
+
+if BUILD_TESTGUI
+SUBDIRS += testgui
+endif
+
+EXTRA_DIST = udev doxygen
+
+dist_doc_DATA = \
+ README.md \
+ AUTHORS.txt \
+ LICENSE-bsd.txt \
+ LICENSE-gpl3.txt \
+ LICENSE-orig.txt \
+ LICENSE.txt
+
+SCMCLEAN_TARGETS= \
+ aclocal.m4 \
+ config.guess \
+ config.sub \
+ configure \
+ config.h.in \
+ depcomp \
+ install-sh \
+ ltmain.sh \
+ missing \
+ mac/Makefile.in \
+ testgui/Makefile.in \
+ libusb/Makefile.in \
+ Makefile.in \
+ linux/Makefile.in \
+ windows/Makefile.in \
+ m4/libtool.m4 \
+ m4/lt~obsolete.m4 \
+ m4/ltoptions.m4 \
+ m4/ltsugar.m4 \
+ m4/ltversion.m4
+
+SCMCLEAN_DIR_TARGETS = \
+ autom4te.cache
+
+scm-clean: distclean
+ rm -f $(SCMCLEAN_TARGETS)
+ rm -Rf $(SCMCLEAN_DIR_TARGETS)
diff --git a/c/src/third-party/hidapi/README b/c/src/third-party/hidapi/README
new file mode 100644
index 000000000..598d4507d
--- /dev/null
+++ b/c/src/third-party/hidapi/README
@@ -0,0 +1,33 @@
+# HIDAPI is being used in the project to communicate with USB and Bluetooth HID devices.
+========================================================================================
+
+
+
+1. License
+HIDAPI can be used under one of three licenses.
+
+1. The GNU General Public License, version 3.0, in LICENSE-gpl3.txt
+2. A BSD-Style License, in LICENSE-bsd.txt.
+3. The more liberal original HIDAPI license. LICENSE-orig.txt
+
+The license chosen is at the discretion of the user of HIDAPI. For example:
+1. An author of GPL software would likely use HIDAPI under the terms of the
+GPL.
+
+2. An author of commercial closed-source software would likely use HIDAPI
+under the terms of the BSD-style license or the original HIDAPI license.
+
+=======================================================================================
+
+2. Project Source
+Ref: https://github.com/libusb/hidapi
+
+=======================================================================================
+
+3. We haven't made any changes to original source as of now
+
+=======================================================================================
+
+4. Keep watching the original project source and pull latest fixes into this repo if required
+
+=======================================================================================
diff --git a/c/src/third-party/hidapi/README.md b/c/src/third-party/hidapi/README.md
new file mode 100644
index 000000000..f5582d7a9
--- /dev/null
+++ b/c/src/third-party/hidapi/README.md
@@ -0,0 +1,380 @@
+## HIDAPI library for Windows, Linux, FreeBSD and macOS
+
+| CI instance | Status |
+|----------------------|--------|
+| `macOS master` | [![Build Status](https://travis-ci.org/libusb/hidapi.svg?branch=master)](https://travis-ci.org/libusb/hidapi) |
+| `Windows master` | [![Build status](https://ci.appveyor.com/api/projects/status/r482aevuigmi86rk/branch/master?svg=true)](https://ci.appveyor.com/project/Youw/hidapi/branch/master) |
+| `Linux/BSD, last build (branch/PR)` | [![builds.sr.ht status](https://builds.sr.ht/~qbicz/hidapi.svg)](https://builds.sr.ht/~qbicz/hidapi?) |
+
+HIDAPI is a multi-platform library which allows an application to interface
+with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS.
+HIDAPI can be either built as a shared library (`.so`, `.dll` or `.dylib`) or
+can be embedded directly into a target application by adding a single source
+file (per platform) and a single header.
+
+HIDAPI library was originally developed by Alan Ott ([signal11](https://github.com/signal11)).
+
+It was moved to [libusb/hidapi](https://github.com/libusb/hidapi) on June 4th, 2019, in order to merge important bugfixes and continue development of the library.
+
+## Table of Contents
+
+* [About](#about)
+* [What Does the API Look Like?](#what-does-the-api-look-like)
+* [License](#license)
+* [Download](#download)
+* [Build Instructions](#build-instructions)
+ * [Prerequisites](#prerequisites)
+ * [Linux](#linux)
+ * [FreeBSD](#freebsd)
+ * [Mac](#mac)
+ * [Windows](#windows)
+ * [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
+ * [Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
+ * [Building on Windows](#building-on-windows)
+* [Cross Compiling](#cross-compiling)
+ * [Prerequisites](#prerequisites-1)
+ * [Building HIDAPI](#building-hidapi)
+
+## About
+
+HIDAPI has five back-ends:
+* Windows (using `hid.dll`)
+* Linux/hidraw (using the Kernel's hidraw driver)
+* Linux/libusb (using libusb-1.0)
+* FreeBSD (using libusb-1.0)
+* Mac (using IOHidManager)
+
+On Linux, either the hidraw or the libusb back-end can be used. There are
+tradeoffs, and the functionality supported is slightly different.
+
+__Linux/hidraw__ (`linux/hid.c`):
+
+This back-end uses the hidraw interface in the Linux kernel, and supports
+both USB and Bluetooth HID devices. It requires kernel version at least 2.6.39
+to build. In addition, it will only communicate with devices which have hidraw
+nodes associated with them.
+Keyboards, mice, and some other devices which are blacklisted from having
+hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw,
+this is not a problem.
+
+__Linux/FreeBSD/libusb__ (`libusb/hid.c`):
+
+This back-end uses libusb-1.0 to communicate directly to a USB device. This
+back-end will of course not work with Bluetooth devices.
+
+HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
+Fox Toolkit . It will build on every platform
+which HIDAPI supports. Since it relies on a 3rd party library, building it
+is optional but recommended because it is so useful when debugging hardware.
+
+## What Does the API Look Like?
+The API provides the most commonly used HID functions including sending
+and receiving of input, output, and feature reports. The sample program,
+which communicates with a heavily hacked up version of the Microchip USB
+Generic HID sample looks like this (with error checking removed for
+simplicity):
+
+**Warning: Only run the code you understand, and only when it conforms to the
+device spec. Writing data at random to your HID devices can break them.**
+
+```c
+#ifdef WIN32
+#include
+#endif
+#include
+#include
+#include "hidapi.h"
+
+#define MAX_STR 255
+
+int main(int argc, char* argv[])
+{
+ int res;
+ unsigned char buf[65];
+ wchar_t wstr[MAX_STR];
+ hid_device *handle;
+ int i;
+
+ // Initialize the hidapi library
+ res = hid_init();
+
+ // Open the device using the VID, PID,
+ // and optionally the Serial number.
+ handle = hid_open(0x4d8, 0x3f, NULL);
+
+ // Read the Manufacturer String
+ res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
+ wprintf(L"Manufacturer String: %s\n", wstr);
+
+ // Read the Product String
+ res = hid_get_product_string(handle, wstr, MAX_STR);
+ wprintf(L"Product String: %s\n", wstr);
+
+ // Read the Serial Number String
+ res = hid_get_serial_number_string(handle, wstr, MAX_STR);
+ wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
+
+ // Read Indexed String 1
+ res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
+ wprintf(L"Indexed String 1: %s\n", wstr);
+
+ // Toggle LED (cmd 0x80). The first byte is the report number (0x0).
+ buf[0] = 0x0;
+ buf[1] = 0x80;
+ res = hid_write(handle, buf, 65);
+
+ // Request state (cmd 0x81). The first byte is the report number (0x0).
+ buf[0] = 0x0;
+ buf[1] = 0x81;
+ res = hid_write(handle, buf, 65);
+
+ // Read requested state
+ res = hid_read(handle, buf, 65);
+
+ // Print out the returned buffer.
+ for (i = 0; i < 4; i++)
+ printf("buf[%d]: %d\n", i, buf[i]);
+
+ // Close the device
+ hid_close(handle);
+
+ // Finalize the hidapi library
+ res = hid_exit();
+
+ return 0;
+}
+```
+
+You can also use [hidtest/test.c](hidtest/test.c)
+as a starting point for your applications.
+
+
+## License
+HIDAPI may be used by one of three licenses as outlined in [LICENSE.txt](LICENSE.txt).
+
+## Download
+HIDAPI can be downloaded from GitHub
+```sh
+git clone git://github.com/libusb/hidapi.git
+```
+
+## Build Instructions
+
+This section is long. Don't be put off by this. It's not long because it's
+complicated to build HIDAPI; it's quite the opposite. This section is long
+because of the flexibility of HIDAPI and the large number of ways in which
+it can be built and used. You will likely pick a single build method.
+
+HIDAPI can be built in several different ways. If you elect to build a
+shared library, you will need to build it from the HIDAPI source
+distribution. If you choose instead to embed HIDAPI directly into your
+application, you can skip the building and look at the provided platform
+Makefiles for guidance. These platform Makefiles are located in `linux/`,
+`libusb/`, `mac/` and `windows/` and are called `Makefile-manual`. In addition,
+Visual Studio projects are provided. Even if you're going to embed HIDAPI
+into your project, it is still beneficial to build the example programs.
+
+
+### Prerequisites:
+
+#### Linux:
+On Linux, you will need to install development packages for libudev,
+libusb and optionally Fox-toolkit (for the test GUI). On
+Debian/Ubuntu systems these can be installed by running:
+```sh
+sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
+```
+
+If you downloaded the source directly from the git repository (using
+git clone), you'll need Autotools:
+```sh
+sudo apt-get install autotools-dev autoconf automake libtool
+```
+
+#### FreeBSD:
+On FreeBSD you will need to install GNU make, libiconv, and
+optionally Fox-Toolkit (for the test GUI). This is done by running
+the following:
+```sh
+pkg_add -r gmake libiconv fox16
+```
+
+If you downloaded the source directly from the git repository (using
+git clone), you'll need Autotools:
+```sh
+pkg_add -r autotools
+```
+
+#### Mac:
+On Mac, you will need to install Fox-Toolkit if you wish to build
+the Test GUI. There are two ways to do this, and each has a slight
+complication. Which method you use depends on your use case.
+
+If you wish to build the Test GUI just for your own testing on your
+own computer, then the easiest method is to install Fox-Toolkit
+using ports:
+```sh
+sudo port install fox
+```
+
+If you wish to build the TestGUI app bundle to redistribute to
+others, you will need to install Fox-toolkit from source. This is
+because the version of fox that gets installed using ports uses the
+ports X11 libraries which are not compatible with the Apple X11
+libraries. If you install Fox with ports and then try to distribute
+your built app bundle, it will simply fail to run on other systems.
+To install Fox-Toolkit manually, download the source package from
+, extract it, and run the following from
+within the extracted source:
+```sh
+./configure && make && make install
+```
+
+#### Windows:
+On Windows, if you want to build the test GUI, you will need to get
+the `hidapi-externals.zip` package from the download site. This
+contains pre-built binaries for Fox-toolkit. Extract
+`hidapi-externals.zip` just outside of hidapi, so that
+hidapi-externals and hidapi are on the same level, as shown:
+```
+ Parent_Folder
+ |
+ +hidapi
+ +hidapi-externals
+```
+Again, this step is not required if you do not wish to build the
+test GUI.
+
+
+### Building HIDAPI into a shared library on Unix Platforms:
+
+On Unix-like systems such as Linux, FreeBSD, macOS, and even Windows, using
+MinGW or Cygwin, the easiest way to build a standard system-installed shared
+library is to use the GNU Autotools build system. If you checked out the
+source from the git repository, run the following:
+
+```sh
+./bootstrap
+./configure
+make
+make install # as root, or using sudo
+```
+
+If you downloaded a source package (i.e.: if you did not run git clone), you
+can skip the `./bootstrap` step.
+
+`./configure` can take several arguments which control the build. The two most
+likely to be used are:
+```sh
+ --enable-testgui
+ Enable build of the Test GUI. This requires Fox toolkit to
+ be installed. Instructions for installing Fox-Toolkit on
+ each platform are in the Prerequisites section above.
+
+ --prefix=/usr
+ Specify where you want the output headers and libraries to
+ be installed. The example above will put the headers in
+ /usr/include and the binaries in /usr/lib. The default is to
+ install into /usr/local which is fine on most systems.
+```
+### Building the manual way on Unix platforms:
+
+Manual Makefiles are provided mostly to give the user and idea what it takes
+to build a program which embeds HIDAPI directly inside of it. These should
+really be used as examples only. If you want to build a system-wide shared
+library, use the Autotools method described above.
+
+To build HIDAPI using the manual Makefiles, change to the directory
+of your platform and run make. For example, on Linux run:
+```sh
+cd linux/
+make -f Makefile-manual
+```
+
+To build the Test GUI using the manual makefiles:
+```sh
+cd testgui/
+make -f Makefile-manual
+```
+
+### Building on Windows:
+
+To build the HIDAPI DLL on Windows using Visual Studio, build the `.sln` file
+in the `windows/` directory.
+
+To build the Test GUI on windows using Visual Studio, build the `.sln` file in
+the `testgui/` directory.
+
+To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
+in the section [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
+above. Note that building the Test GUI with MinGW or Cygwin will
+require the Windows procedure in the [Prerequisites](#prerequisites-1) section
+above (i.e.: `hidapi-externals.zip`).
+
+To build HIDAPI using MinGW using the Manual Makefiles, see the section
+[Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
+above.
+
+HIDAPI can also be built using the Windows DDK (now also called the Windows
+Driver Kit or WDK). This method was originally required for the HIDAPI build
+but not anymore. However, some users still prefer this method. It is not as
+well supported anymore but should still work. Patches are welcome if it does
+not. To build using the DDK:
+
+ 1. Install the Windows Driver Kit (WDK) from Microsoft.
+ 2. From the Start menu, in the Windows Driver Kits folder, select Build
+ Environments, then your operating system, then the x86 Free Build
+ Environment (or one that is appropriate for your system).
+ 3. From the console, change directory to the `windows/ddk_build/` directory,
+ which is part of the HIDAPI distribution.
+ 4. Type build.
+ 5. You can find the output files (DLL and LIB) in a subdirectory created
+ by the build system which is appropriate for your environment. On
+ Windows XP, this directory is `objfre_wxp_x86/i386`.
+
+## Cross Compiling
+
+This section talks about cross compiling HIDAPI for Linux using Autotools.
+This is useful for using HIDAPI on embedded Linux targets. These
+instructions assume the most raw kind of embedded Linux build, where all
+prerequisites will need to be built first. This process will of course vary
+based on your embedded Linux build system if you are using one, such as
+OpenEmbedded or Buildroot.
+
+For the purpose of this section, it will be assumed that the following
+environment variables are exported.
+```sh
+$ export STAGING=$HOME/out
+$ export HOST=arm-linux
+```
+
+`STAGING` and `HOST` can be modified to suit your setup.
+
+### Prerequisites
+
+Note that the build of libudev is the very basic configuration.
+
+Build libusb. From the libusb source directory, run:
+```sh
+./configure --host=$HOST --prefix=$STAGING
+make
+make install
+```
+
+Build libudev. From the libudev source directory, run:
+```sh
+./configure --disable-gudev --disable-introspection --disable-hwdb \
+ --host=$HOST --prefix=$STAGING
+make
+make install
+```
+
+### Building HIDAPI
+
+Build HIDAPI:
+```
+PKG_CONFIG_DIR= \
+PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
+PKG_CONFIG_SYSROOT_DIR=$STAGING \
+./configure --host=$HOST --prefix=$STAGING
+```
diff --git a/c/src/third-party/hidapi/android/jni/Android.mk b/c/src/third-party/hidapi/android/jni/Android.mk
new file mode 100644
index 000000000..527b43fd6
--- /dev/null
+++ b/c/src/third-party/hidapi/android/jni/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+
+HIDAPI_ROOT_REL:= ../..
+HIDAPI_ROOT_ABS:= $(LOCAL_PATH)/../..
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(HIDAPI_ROOT_REL)/libusb/hid.c
+
+LOCAL_C_INCLUDES += \
+ $(HIDAPI_ROOT_ABS)/hidapi \
+ $(HIDAPI_ROOT_ABS)/android
+
+LOCAL_SHARED_LIBRARIES := libusb1.0
+
+LOCAL_MODULE := libhidapi
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/c/src/third-party/hidapi/bootstrap b/c/src/third-party/hidapi/bootstrap
new file mode 100755
index 000000000..81e9b74b6
--- /dev/null
+++ b/c/src/third-party/hidapi/bootstrap
@@ -0,0 +1,2 @@
+#!/bin/sh -x
+autoreconf --install --verbose --force
diff --git a/c/src/third-party/hidapi/configure.ac b/c/src/third-party/hidapi/configure.ac
new file mode 100644
index 000000000..a8f2a84cb
--- /dev/null
+++ b/c/src/third-party/hidapi/configure.ac
@@ -0,0 +1,252 @@
+AC_PREREQ(2.63)
+
+# Version number. This is currently the only place.
+m4_define([HIDAPI_MAJOR], 0)
+m4_define([HIDAPI_MINOR], 9)
+m4_define([HIDAPI_RELEASE], 0)
+m4_define([HIDAPI_RC], )
+m4_define([VERSION_STRING], HIDAPI_MAJOR[.]HIDAPI_MINOR[.]HIDAPI_RELEASE[]HIDAPI_RC)
+
+AC_INIT([hidapi],[VERSION_STRING],[alan@signal11.us])
+
+# Library soname version
+# Follow the following rules (particularly the ones in the second link):
+# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+# http://sourceware.org/autobook/autobook/autobook_91.html
+lt_current="0"
+lt_revision="0"
+lt_age="0"
+LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}"
+
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE([foreign -Wall -Werror])
+AC_CONFIG_MACRO_DIR([m4])
+
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+LT_INIT
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_OBJC
+PKG_PROG_PKG_CONFIG
+
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+hidapi_lib_error() {
+ echo ""
+ echo " Library $1 was not found on this system."
+ echo " Please install it and re-run ./configure"
+ echo ""
+ exit 1
+}
+
+hidapi_prog_error() {
+ echo ""
+ echo " Program $1 was not found on this system."
+ echo " This program is part of $2."
+ echo " Please install it and re-run ./configure"
+ echo ""
+ exit 1
+}
+
+AC_MSG_CHECKING([operating system])
+AC_MSG_RESULT($host)
+case $host in
+*-linux*)
+ AC_MSG_RESULT([ (Linux back-end)])
+ AC_DEFINE(OS_LINUX, 1, [Linux implementations])
+ AC_SUBST(OS_LINUX)
+ backend="linux"
+ os="linux"
+ threads="pthreads"
+
+ # HIDAPI/hidraw libs
+ PKG_CHECK_MODULES([libudev], [libudev], true, [hidapi_lib_error libudev])
+ LIBS_HIDRAW_PR="${LIBS_HIDRAW_PR} $libudev_LIBS"
+ CFLAGS_HIDRAW="${CFLAGS_HIDRAW} $libudev_CFLAGS"
+
+ # HIDAPI/libusb libs
+ AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lrt"], [hidapi_lib_error librt])
+ PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
+ LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
+ CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
+ ;;
+*-darwin*)
+ AC_MSG_RESULT([ (Mac OS X back-end)])
+ AC_DEFINE(OS_DARWIN, 1, [Mac implementation])
+ AC_SUBST(OS_DARWIN)
+ backend="mac"
+ os="darwin"
+ threads="pthreads"
+ LIBS="${LIBS} -framework IOKit -framework CoreFoundation"
+ ;;
+*-freebsd*)
+ AC_MSG_RESULT([ (FreeBSD back-end)])
+ AC_DEFINE(OS_FREEBSD, 1, [FreeBSD implementation])
+ AC_SUBST(OS_FREEBSD)
+ backend="libusb"
+ os="freebsd"
+ threads="pthreads"
+
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ LIBS="${LIBS}"
+ PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
+ LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
+ CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
+ AC_CHECK_LIB([iconv], [iconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
+ ;;
+*-kfreebsd*)
+ AC_MSG_RESULT([ (kFreeBSD back-end)])
+ AC_DEFINE(OS_KFREEBSD, 1, [kFreeBSD implementation])
+ AC_SUBST(OS_KFREEBSD)
+ backend="libusb"
+ os="kfreebsd"
+ threads="pthreads"
+
+ PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
+ LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
+ CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
+ ;;
+*-*-haiku)
+ AC_MSG_RESULT([ (Haiku back-end)])
+ AC_DEFINE(OS_HAIKU, 1, [Haiku implementation])
+ AC_SUBST(OS_HAIKU)
+ backend="libusb"
+ os="haiku"
+ threads="pthreads"
+
+ PKG_CHECK_MODULES([libusb], [libusb-1.0 >= 1.0.9], true, [hidapi_lib_error libusb-1.0])
+ LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} $libusb_LIBS"
+ CFLAGS_LIBUSB="${CFLAGS_LIBUSB} $libusb_CFLAGS"
+ AC_CHECK_LIB([iconv], [libiconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv])
+ ;;
+*-mingw*)
+ AC_MSG_RESULT([ (Windows back-end, using MinGW)])
+ backend="windows"
+ os="windows"
+ threads="windows"
+ win_implementation="mingw"
+ ;;
+*-cygwin*)
+ AC_MSG_RESULT([ (Windows back-end, using Cygwin)])
+ backend="windows"
+ os="windows"
+ threads="windows"
+ win_implementation="cygwin"
+ ;;
+*)
+ AC_MSG_ERROR([HIDAPI is not supported on your operating system yet])
+esac
+
+LIBS_HIDRAW="${LIBS} ${LIBS_HIDRAW_PR}"
+LIBS_LIBUSB="${LIBS} ${LIBS_LIBUSB_PRIVATE}"
+AC_SUBST([LIBS_HIDRAW])
+AC_SUBST([LIBS_LIBUSB])
+AC_SUBST([CFLAGS_LIBUSB])
+AC_SUBST([CFLAGS_HIDRAW])
+
+if test "x$os" = xwindows; then
+ AC_DEFINE(OS_WINDOWS, 1, [Windows implementations])
+ AC_SUBST(OS_WINDOWS)
+ LDFLAGS="${LDFLAGS} -no-undefined"
+ LIBS="${LIBS} -lsetupapi"
+fi
+
+if test "x$threads" = xpthreads; then
+ AX_PTHREAD([found_pthreads=yes], [found_pthreads=no])
+
+ if test "x$found_pthreads" = xyes; then
+ if test "x$os" = xlinux; then
+ # Only use pthreads for libusb implementation on Linux.
+ LIBS_LIBUSB="$PTHREAD_LIBS $LIBS_LIBUSB"
+ CFLAGS_LIBUSB="$CFLAGS_LIBUSB $PTHREAD_CFLAGS"
+ # There's no separate CC on Linux for threading,
+ # so it's ok that both implementations use $PTHREAD_CC
+ CC="$PTHREAD_CC"
+ else
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ CC="$PTHREAD_CC"
+ fi
+ fi
+fi
+
+# Test GUI
+AC_ARG_ENABLE([testgui],
+ [AS_HELP_STRING([--enable-testgui],
+ [enable building of test GUI (default n)])],
+ [testgui_enabled=$enableval],
+ [testgui_enabled='no'])
+AM_CONDITIONAL([BUILD_TESTGUI], [test "x$testgui_enabled" != "xno"])
+
+# Configure the MacOS TestGUI app bundle
+rm -Rf testgui/TestGUI.app
+mkdir -p testgui/TestGUI.app
+cp -R ${srcdir}/testgui/TestGUI.app.in/* testgui/TestGUI.app
+chmod -R u+w testgui/TestGUI.app
+mkdir testgui/TestGUI.app/Contents/MacOS/
+
+if test "x$testgui_enabled" != "xno"; then
+ if test "x$os" = xdarwin; then
+ # On Mac OS, don't use pkg-config.
+ AC_CHECK_PROG([foxconfig], [fox-config], [fox-config], false)
+ if test "x$foxconfig" = "xfalse"; then
+ hidapi_prog_error fox-config "FOX Toolkit"
+ fi
+ LIBS_TESTGUI="${LIBS_TESTGUI} `$foxconfig --libs`"
+ LIBS_TESTGUI="${LIBS_TESTGUI} -framework Cocoa -L/usr/X11R6/lib"
+ CFLAGS_TESTGUI="${CFLAGS_TESTGUI} `$foxconfig --cflags`"
+ OBJCFLAGS="${OBJCFLAGS} -x objective-c++"
+ elif test "x$os" = xwindows; then
+ # On Windows, just set the paths for Fox toolkit
+ if test "x$win_implementation" = xmingw; then
+ CFLAGS_TESTGUI="-I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
+ LIBS_TESTGUI=" -mwindows \$(srcdir)/../../hidapi-externals/fox/lib/libFOX-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
+ else
+ # Cygwin
+ CFLAGS_TESTGUI="-DWIN32 -I\$(srcdir)/../../hidapi-externals/fox/include -g -c"
+ LIBS_TESTGUI="\$(srcdir)/../../hidapi-externals/fox/lib/libFOX-cygwin-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32"
+ fi
+ else
+ # On Linux and FreeBSD platforms, use pkg-config to find fox.
+ PKG_CHECK_MODULES([fox], [fox17], [], [PKG_CHECK_MODULES([fox], [fox])])
+ LIBS_TESTGUI="${LIBS_TESTGUI} $fox_LIBS"
+ if test "x$os" = xfreebsd; then
+ LIBS_TESTGUI="${LIBS_TESTGUI} -L/usr/local/lib"
+ fi
+ CFLAGS_TESTGUI="${CFLAGS_TESTGUI} $fox_CFLAGS"
+ fi
+fi
+AC_SUBST([LIBS_TESTGUI])
+AC_SUBST([CFLAGS_TESTGUI])
+AC_SUBST([backend])
+
+# OS info for Automake
+AM_CONDITIONAL(OS_LINUX, test "x$os" = xlinux)
+AM_CONDITIONAL(OS_DARWIN, test "x$os" = xdarwin)
+AM_CONDITIONAL(OS_FREEBSD, test "x$os" = xfreebsd)
+AM_CONDITIONAL(OS_KFREEBSD, test "x$os" = xkfreebsd)
+AM_CONDITIONAL(OS_HAIKU, test "x$os" = xhaiku)
+AM_CONDITIONAL(OS_WINDOWS, test "x$os" = xwindows)
+
+AC_CONFIG_HEADERS([config.h])
+
+if test "x$os" = "xlinux"; then
+ AC_CONFIG_FILES([pc/hidapi-hidraw.pc])
+ AC_CONFIG_FILES([pc/hidapi-libusb.pc])
+else
+ AC_CONFIG_FILES([pc/hidapi.pc])
+fi
+
+AC_SUBST(LTLDFLAGS)
+
+AC_CONFIG_FILES([Makefile \
+ hidtest/Makefile \
+ libusb/Makefile \
+ linux/Makefile \
+ mac/Makefile \
+ testgui/Makefile \
+ windows/Makefile])
+AC_OUTPUT
diff --git a/c/src/third-party/hidapi/dist/hidapi.podspec b/c/src/third-party/hidapi/dist/hidapi.podspec
new file mode 100644
index 000000000..f5449f978
--- /dev/null
+++ b/c/src/third-party/hidapi/dist/hidapi.podspec
@@ -0,0 +1,31 @@
+Pod::Spec.new do |spec|
+
+ spec.name = "hidapi"
+ spec.version = "0.9.0"
+ spec.summary = "A Simple library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows."
+
+ spec.description = <<-DESC
+ HIDAPI is a multi-platform library which allows an application to interface with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS. HIDAPI can be either built as a shared library (.so, .dll or .dylib) or can be embedded directly into a target application by adding a single source file (per platform) and a single header.
+ DESC
+
+ spec.homepage = "https://github.com/libusb/hidapi"
+
+ spec.license = { :type=> "GNU GPLv3 or BSD or HIDAPI original", :file => "LICENSE.txt" }
+
+ spec.authors = { "Alan Ott" => "alan@signal11.us",
+ "Ludovic Rousseau" => "rousseau@debian.org",
+ "libusb/hidapi Team" => "https://github.com/libusb/hidapi/blob/master/AUTHORS.txt",
+ }
+
+ spec.platform = :osx
+ spec.osx.deployment_target = "10.7"
+
+ spec.source = { :git => "https://github.com/libusb/hidapi.git", :tag => "hidapi-#{spec.version}" }
+
+ spec.source_files = "mac/hid.c", "hidapi/hidapi.h"
+
+ spec.public_header_files = "hidapi/hidapi.h"
+
+ spec.frameworks = "IOKit", "CoreFoundation"
+
+end
diff --git a/c/src/third-party/hidapi/doxygen/Doxyfile b/c/src/third-party/hidapi/doxygen/Doxyfile
new file mode 100644
index 000000000..b1ea0a223
--- /dev/null
+++ b/c/src/third-party/hidapi/doxygen/Doxyfile
@@ -0,0 +1,2482 @@
+# Doxyfile 1.8.15
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = hidapi
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is
+# Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if ... \endif and \cond
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ../hidapi
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+#
+#
+# where is the value of the INPUT_FILTER tag, and is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use + S
+# (what the is depends on the OS and browser, but it is typically
+# , /, or both). Inside the search box use the to jump into the search results window, the results can be navigated
+# using the . Press to select an item or to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing +. Also here use the
+# to select a filter and or to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: \makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = \makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = FreeSans.ttf
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/c/src/third-party/hidapi/hidapi/hidapi.h b/c/src/third-party/hidapi/hidapi/hidapi.h
new file mode 100644
index 000000000..4102e6c17
--- /dev/null
+++ b/c/src/third-party/hidapi/hidapi/hidapi.h
@@ -0,0 +1,446 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ https://github.com/libusb/hidapi .
+********************************************************/
+
+/** @file
+ * @defgroup API hidapi API
+ */
+
+#ifndef HIDAPI_H__
+#define HIDAPI_H__
+
+#include
+
+#ifdef _WIN32
+ #define HID_API_EXPORT __declspec(dllexport)
+ #define HID_API_CALL
+#else
+ #define HID_API_EXPORT /**< API export macro */
+ #define HID_API_CALL /**< API call macro */
+#endif
+
+#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ struct hid_device_;
+ typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
+
+ /** hidapi info structure */
+ struct hid_device_info {
+ /** Platform-specific device path */
+ char *path;
+ /** Device Vendor ID */
+ unsigned short vendor_id;
+ /** Device Product ID */
+ unsigned short product_id;
+ /** Serial Number */
+ wchar_t *serial_number;
+ /** Device Release Number in binary-coded decimal,
+ also known as Device Version Number */
+ unsigned short release_number;
+ /** Manufacturer String */
+ wchar_t *manufacturer_string;
+ /** Product string */
+ wchar_t *product_string;
+ /** Usage Page for this Device/Interface
+ (Windows/Mac only). */
+ unsigned short usage_page;
+ /** Usage for this Device/Interface
+ (Windows/Mac only).*/
+ unsigned short usage;
+ /** The USB interface which this logical device
+ represents.
+
+ * Valid on both Linux implementations in all cases.
+ * Valid on the Windows implementation only if the device
+ contains more than one interface.
+ * Valid on the Mac implementation if and only if the device
+ is a USB HID device. */
+ int interface_number;
+
+ /** Pointer to the next device */
+ struct hid_device_info *next;
+ };
+
+
+ /** @brief Initialize the HIDAPI library.
+
+ This function initializes the HIDAPI library. Calling it is not
+ strictly necessary, as it will be called automatically by
+ hid_enumerate() and any of the hid_open_*() functions if it is
+ needed. This function should be called at the beginning of
+ execution however, if there is a chance of HIDAPI handles
+ being opened by different threads simultaneously.
+
+ @ingroup API
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_init(void);
+
+ /** @brief Finalize the HIDAPI library.
+
+ This function frees all of the static data associated with
+ HIDAPI. It should be called at the end of execution to avoid
+ memory leaks.
+
+ @ingroup API
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_exit(void);
+
+ /** @brief Enumerate the HID Devices.
+
+ This function returns a linked list of all the HID devices
+ attached to the system which match vendor_id and product_id.
+ If @p vendor_id is set to 0 then any vendor matches.
+ If @p product_id is set to 0 then any product matches.
+ If @p vendor_id and @p product_id are both set to 0, then
+ all HID devices will be returned.
+
+ @ingroup API
+ @param vendor_id The Vendor ID (VID) of the types of device
+ to open.
+ @param product_id The Product ID (PID) of the types of
+ device to open.
+
+ @returns
+ This function returns a pointer to a linked list of type
+ struct #hid_device_info, containing information about the HID devices
+ attached to the system, or NULL in the case of failure. Free
+ this linked list by calling hid_free_enumeration().
+ */
+ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
+
+ /** @brief Free an enumeration Linked List
+
+ This function frees a linked list created by hid_enumerate().
+
+ @ingroup API
+ @param devs Pointer to a list of struct_device returned from
+ hid_enumerate().
+ */
+ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
+
+ /** @brief Open a HID device using a Vendor ID (VID), Product ID
+ (PID) and optionally a serial number.
+
+ If @p serial_number is NULL, the first device with the
+ specified VID and PID is opened.
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param vendor_id The Vendor ID (VID) of the device to open.
+ @param product_id The Product ID (PID) of the device to open.
+ @param serial_number The Serial Number of the device to open
+ (Optionally NULL).
+
+ @returns
+ This function returns a pointer to a #hid_device object on
+ success or NULL on failure.
+ */
+ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
+
+ /** @brief Open a HID device by its path name.
+
+ The path name be determined by calling hid_enumerate(), or a
+ platform-specific path name can be used (eg: /dev/hidraw0 on
+ Linux).
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param path The path name of the device to open
+
+ @returns
+ This function returns a pointer to a #hid_device object on
+ success or NULL on failure.
+ */
+ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
+
+ /** @brief Write an Output report to a HID device.
+
+ The first byte of @p data[] must contain the Report ID. For
+ devices which only support a single report, this must be set
+ to 0x0. The remaining bytes contain the report data. Since
+ the Report ID is mandatory, calls to hid_write() will always
+ contain one more byte than the report contains. For example,
+ if a hid report is 16 bytes long, 17 bytes must be passed to
+ hid_write(), the Report ID (or 0x0, for devices with a
+ single report), followed by the report data (16 bytes). In
+ this example, the length passed in would be 17.
+
+ hid_write() will send the data on the first OUT endpoint, if
+ one exists. If it does not, it will send the data through
+ the Control Endpoint (Endpoint 0).
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param data The data to send, including the report number as
+ the first byte.
+ @param length The length in bytes of the data to send.
+
+ @returns
+ This function returns the actual number of bytes written and
+ -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length);
+
+ /** @brief Read an Input report from a HID device with timeout.
+
+ Input reports are returned
+ to the host through the INTERRUPT IN endpoint. The first byte will
+ contain the Report number if the device uses numbered reports.
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param data A buffer to put the read data into.
+ @param length The number of bytes to read. For devices with
+ multiple reports, make sure to read an extra byte for
+ the report number.
+ @param milliseconds timeout in milliseconds or -1 for blocking wait.
+
+ @returns
+ This function returns the actual number of bytes read and
+ -1 on error. If no packet was available to be read within
+ the timeout period, this function returns 0.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
+
+ /** @brief Read an Input report from a HID device.
+
+ Input reports are returned
+ to the host through the INTERRUPT IN endpoint. The first byte will
+ contain the Report number if the device uses numbered reports.
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param data A buffer to put the read data into.
+ @param length The number of bytes to read. For devices with
+ multiple reports, make sure to read an extra byte for
+ the report number.
+
+ @returns
+ This function returns the actual number of bytes read and
+ -1 on error. If no packet was available to be read and
+ the handle is in non-blocking mode, this function returns 0.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);
+
+ /** @brief Set the device handle to be non-blocking.
+
+ In non-blocking mode calls to hid_read() will return
+ immediately with a value of 0 if there is no data to be
+ read. In blocking mode, hid_read() will wait (block) until
+ there is data to read before returning.
+
+ Nonblocking can be turned on and off at any time.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param nonblock enable or not the nonblocking reads
+ - 1 to enable nonblocking
+ - 0 to disable nonblocking.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);
+
+ /** @brief Send a Feature report to the device.
+
+ Feature reports are sent over the Control endpoint as a
+ Set_Report transfer. The first byte of @p data[] must
+ contain the Report ID. For devices which only support a
+ single report, this must be set to 0x0. The remaining bytes
+ contain the report data. Since the Report ID is mandatory,
+ calls to hid_send_feature_report() will always contain one
+ more byte than the report contains. For example, if a hid
+ report is 16 bytes long, 17 bytes must be passed to
+ hid_send_feature_report(): the Report ID (or 0x0, for
+ devices which do not use numbered reports), followed by the
+ report data (16 bytes). In this example, the length passed
+ in would be 17.
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param data The data to send, including the report number as
+ the first byte.
+ @param length The length in bytes of the data to send, including
+ the report number.
+
+ @returns
+ This function returns the actual number of bytes written and
+ -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length);
+
+ /** @brief Get a feature report from a HID device.
+
+ Set the first byte of @p data[] to the Report ID of the
+ report to be read. Make sure to allow space for this
+ extra byte in @p data[]. Upon return, the first byte will
+ still contain the Report ID, and the report data will
+ start in data[1].
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param data A buffer to put the read data into, including
+ the Report ID. Set the first byte of @p data[] to the
+ Report ID of the report to be read, or set it to zero
+ if your device does not use numbered reports.
+ @param length The number of bytes to read, including an
+ extra byte for the report ID. The buffer can be longer
+ than the actual report.
+
+ @returns
+ This function returns the number of bytes read plus
+ one for the report ID (which is still in the first
+ byte), or -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
+
+ /** @brief Get a input report from a HID device.
+
+ Set the first byte of @p data[] to the Report ID of the
+ report to be read. Make sure to allow space for this
+ extra byte in @p data[]. Upon return, the first byte will
+ still contain the Report ID, and the report data will
+ start in data[1].
+
+ @ingroup API
+ @param device A device handle returned from hid_open().
+ @param data A buffer to put the read data into, including
+ the Report ID. Set the first byte of @p data[] to the
+ Report ID of the report to be read, or set it to zero
+ if your device does not use numbered reports.
+ @param length The number of bytes to read, including an
+ extra byte for the report ID. The buffer can be longer
+ than the actual report.
+
+ @returns
+ This function returns the number of bytes read plus
+ one for the report ID (which is still in the first
+ byte), or -1 on error.
+ */
+ int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
+
+ /** @brief Close a HID device.
+
+ This function sets the return value of hid_error().
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ */
+ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev);
+
+ /** @brief Get The Manufacturer String from a HID device.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
+
+ /** @brief Get The Product String from a HID device.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);
+
+ /** @brief Get The Serial Number String from a HID device.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen);
+
+ /** @brief Get a string from a HID device, based on its string index.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open().
+ @param string_index The index of the string to get.
+ @param string A wide string buffer to put the data into.
+ @param maxlen The length of the buffer in multiples of wchar_t.
+
+ @returns
+ This function returns 0 on success and -1 on error.
+ */
+ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
+
+ /** @brief Get a string describing the last error which occurred.
+
+ Whether a function sets the last error is noted in its
+ documentation. These functions will reset the last error
+ to NULL before their execution.
+
+ Strings returned from hid_error() must not be freed by the user!
+
+ This function is thread-safe, and error messages are thread-local.
+
+ @ingroup API
+ @param dev A device handle returned from hid_open(),
+ or NULL to get the last non-device-specific error
+ (e.g. for errors in hid_open() itself).
+
+ @returns
+ This function returns a string containing the last error
+ which occurred or NULL if none has occurred.
+ */
+ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/c/src/third-party/hidapi/hidtest/.gitignore b/c/src/third-party/hidapi/hidtest/.gitignore
new file mode 100644
index 000000000..a9ce7a23b
--- /dev/null
+++ b/c/src/third-party/hidapi/hidtest/.gitignore
@@ -0,0 +1,17 @@
+Debug
+Release
+*.exp
+*.ilk
+*.lib
+*.suo
+*.vcproj.*
+*.ncb
+*.suo
+*.dll
+*.pdb
+*.o
+.deps/
+.libs/
+hidtest-hidraw
+hidtest-libusb
+hidtest
diff --git a/c/src/third-party/hidapi/hidtest/Makefile.am b/c/src/third-party/hidapi/hidtest/Makefile.am
new file mode 100644
index 000000000..4fb01e121
--- /dev/null
+++ b/c/src/third-party/hidapi/hidtest/Makefile.am
@@ -0,0 +1,20 @@
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
+
+## Linux
+if OS_LINUX
+noinst_PROGRAMS = hidtest-libusb hidtest-hidraw
+
+hidtest_hidraw_SOURCES = test.c
+hidtest_hidraw_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la
+
+hidtest_libusb_SOURCES = test.c
+hidtest_libusb_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la
+else
+
+# Other OS's
+noinst_PROGRAMS = hidtest
+
+hidtest_SOURCES = test.c
+hidtest_LDADD = $(top_builddir)/$(backend)/libhidapi.la
+
+endif
diff --git a/c/src/third-party/hidapi/hidtest/test.c b/c/src/third-party/hidapi/hidtest/test.c
new file mode 100644
index 000000000..857300a58
--- /dev/null
+++ b/c/src/third-party/hidapi/hidtest/test.c
@@ -0,0 +1,195 @@
+/*******************************************************
+ Windows HID simplification
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+
+ Copyright 2009
+
+ This contents of this file may be used by anyone
+ for any reason without any conditions and may be
+ used as a starting point for your own applications
+ which use HIDAPI.
+********************************************************/
+
+#include
+#include
+#include
+#include
+#include "hidapi.h"
+
+// Headers needed for sleeping.
+#ifdef _WIN32
+ #include
+#else
+ #include
+#endif
+
+int main(int argc, char* argv[])
+{
+ int res;
+ unsigned char buf[256];
+ #define MAX_STR 255
+ wchar_t wstr[MAX_STR];
+ hid_device *handle;
+ int i;
+
+#ifdef WIN32
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+#endif
+
+ struct hid_device_info *devs, *cur_dev;
+
+ if (hid_init())
+ return -1;
+
+ devs = hid_enumerate(0x0, 0x0);
+ cur_dev = devs;
+ while (cur_dev) {
+ printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
+ printf("\n");
+ printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
+ printf(" Product: %ls\n", cur_dev->product_string);
+ printf(" Release: %hx\n", cur_dev->release_number);
+ printf(" Interface: %d\n", cur_dev->interface_number);
+ printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
+ printf("\n");
+ cur_dev = cur_dev->next;
+ }
+ hid_free_enumeration(devs);
+
+ // Set up the command buffer.
+ memset(buf,0x00,sizeof(buf));
+ buf[0] = 0x01;
+ buf[1] = 0x81;
+
+
+ // Open the device using the VID, PID,
+ // and optionally the Serial number.
+ ////handle = hid_open(0x4d8, 0x3f, L"12345");
+ handle = hid_open(0x4d8, 0x3f, NULL);
+ if (!handle) {
+ printf("unable to open device\n");
+ return 1;
+ }
+
+ // Read the Manufacturer String
+ wstr[0] = 0x0000;
+ res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
+ if (res < 0)
+ printf("Unable to read manufacturer string\n");
+ printf("Manufacturer String: %ls\n", wstr);
+
+ // Read the Product String
+ wstr[0] = 0x0000;
+ res = hid_get_product_string(handle, wstr, MAX_STR);
+ if (res < 0)
+ printf("Unable to read product string\n");
+ printf("Product String: %ls\n", wstr);
+
+ // Read the Serial Number String
+ wstr[0] = 0x0000;
+ res = hid_get_serial_number_string(handle, wstr, MAX_STR);
+ if (res < 0)
+ printf("Unable to read serial number string\n");
+ printf("Serial Number String: (%d) %ls", wstr[0], wstr);
+ printf("\n");
+
+ // Read Indexed String 1
+ wstr[0] = 0x0000;
+ res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
+ if (res < 0)
+ printf("Unable to read indexed string 1\n");
+ printf("Indexed String 1: %ls\n", wstr);
+
+ // Set the hid_read() function to be non-blocking.
+ hid_set_nonblocking(handle, 1);
+
+ // Try to read from the device. There should be no
+ // data here, but execution should not block.
+ res = hid_read(handle, buf, 17);
+
+ // Send a Feature Report to the device
+ buf[0] = 0x2;
+ buf[1] = 0xa0;
+ buf[2] = 0x0a;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ res = hid_send_feature_report(handle, buf, 17);
+ if (res < 0) {
+ printf("Unable to send a feature report.\n");
+ }
+
+ memset(buf,0,sizeof(buf));
+
+ // Read a Feature Report from the device
+ buf[0] = 0x2;
+ res = hid_get_feature_report(handle, buf, sizeof(buf));
+ if (res < 0) {
+ printf("Unable to get a feature report.\n");
+ printf("%ls", hid_error(handle));
+ }
+ else {
+ // Print out the returned buffer.
+ printf("Feature Report\n ");
+ for (i = 0; i < res; i++)
+ printf("%02hhx ", buf[i]);
+ printf("\n");
+ }
+
+ memset(buf,0,sizeof(buf));
+
+ // Toggle LED (cmd 0x80). The first byte is the report number (0x1).
+ buf[0] = 0x1;
+ buf[1] = 0x80;
+ res = hid_write(handle, buf, 17);
+ if (res < 0) {
+ printf("Unable to write()\n");
+ printf("Error: %ls\n", hid_error(handle));
+ }
+
+
+ // Request state (cmd 0x81). The first byte is the report number (0x1).
+ buf[0] = 0x1;
+ buf[1] = 0x81;
+ hid_write(handle, buf, 17);
+ if (res < 0)
+ printf("Unable to write() (2)\n");
+
+ // Read requested state. hid_read() has been set to be
+ // non-blocking by the call to hid_set_nonblocking() above.
+ // This loop demonstrates the non-blocking nature of hid_read().
+ res = 0;
+ while (res == 0) {
+ res = hid_read(handle, buf, sizeof(buf));
+ if (res == 0)
+ printf("waiting...\n");
+ if (res < 0)
+ printf("Unable to read()\n");
+ #ifdef WIN32
+ Sleep(500);
+ #else
+ usleep(500*1000);
+ #endif
+ }
+
+ printf("Data read:\n ");
+ // Print out the returned buffer.
+ for (i = 0; i < res; i++)
+ printf("%02hhx ", buf[i]);
+ printf("\n");
+
+ hid_close(handle);
+
+ /* Free static HIDAPI objects. */
+ hid_exit();
+
+#ifdef WIN32
+ system("pause");
+#endif
+
+ return 0;
+}
diff --git a/c/src/third-party/hidapi/libusb/.gitignore b/c/src/third-party/hidapi/libusb/.gitignore
new file mode 100644
index 000000000..67460db93
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.so
+*.la
+*.lo
+*.a
+.libs
+.deps
+hidtest-libusb
diff --git a/c/src/third-party/hidapi/libusb/Makefile-manual b/c/src/third-party/hidapi/libusb/Makefile-manual
new file mode 100644
index 000000000..0acf707a4
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/Makefile-manual
@@ -0,0 +1,22 @@
+
+
+OS=$(shell uname)
+
+ifeq ($(OS), Linux)
+ FILE=Makefile.linux
+endif
+
+ifeq ($(OS), FreeBSD)
+ FILE=Makefile.freebsd
+endif
+
+ifeq ($(OS), Haiku)
+ FILE=Makefile.haiku
+endif
+
+ifeq ($(FILE), )
+all:
+ $(error Your platform ${OS} is not supported by hidapi/libusb at this time.)
+endif
+
+include $(FILE)
diff --git a/c/src/third-party/hidapi/libusb/Makefile.am b/c/src/third-party/hidapi/libusb/Makefile.am
new file mode 100644
index 000000000..1da06bc16
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/Makefile.am
@@ -0,0 +1,34 @@
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi $(CFLAGS_LIBUSB)
+
+if OS_LINUX
+lib_LTLIBRARIES = libhidapi-libusb.la
+libhidapi_libusb_la_SOURCES = hid.c
+libhidapi_libusb_la_LDFLAGS = $(LTLDFLAGS) $(PTHREAD_CFLAGS)
+libhidapi_libusb_la_LIBADD = $(LIBS_LIBUSB)
+endif
+
+if OS_FREEBSD
+lib_LTLIBRARIES = libhidapi.la
+libhidapi_la_SOURCES = hid.c
+libhidapi_la_LDFLAGS = $(LTLDFLAGS)
+libhidapi_la_LIBADD = $(LIBS_LIBUSB)
+endif
+
+if OS_KFREEBSD
+lib_LTLIBRARIES = libhidapi.la
+libhidapi_la_SOURCES = hid.c
+libhidapi_la_LDFLAGS = $(LTLDFLAGS)
+libhidapi_la_LIBADD = $(LIBS_LIBUSB)
+endif
+
+if OS_HAIKU
+lib_LTLIBRARIES = libhidapi.la
+libhidapi_la_SOURCES = hid.c
+libhidapi_la_LDFLAGS = $(LTLDFLAGS)
+libhidapi_la_LIBADD = $(LIBS_LIBUSB)
+endif
+
+hdrdir = $(includedir)/hidapi
+hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
+
+EXTRA_DIST = Makefile-manual
diff --git a/c/src/third-party/hidapi/libusb/Makefile.freebsd b/c/src/third-party/hidapi/libusb/Makefile.freebsd
new file mode 100644
index 000000000..cb24d6a94
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/Makefile.freebsd
@@ -0,0 +1,39 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidtest libs
+
+libs: libhidapi.so
+
+CC ?= cc
+CFLAGS ?= -Wall -g -fPIC
+
+COBJS = hid.o ../hidtest/test.o
+OBJS = $(COBJS)
+INCLUDES = -I../hidapi -I/usr/local/include
+LDFLAGS = -L/usr/local/lib
+LIBS = -lusb -liconv -pthread
+
+
+# Console Test Program
+hidtest: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
+
+# Shared Libs
+libhidapi.so: $(COBJS)
+ $(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS)
+
+# Objects
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
+
+
+clean:
+ rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
+
+.PHONY: clean libs
diff --git a/c/src/third-party/hidapi/libusb/Makefile.haiku b/c/src/third-party/hidapi/libusb/Makefile.haiku
new file mode 100644
index 000000000..975e8ba67
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/Makefile.haiku
@@ -0,0 +1,39 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidtest libs
+
+libs: libhidapi.so
+
+CC ?= cc
+CFLAGS ?= -Wall -g -fPIC
+
+COBJS = hid.o ../hidtest/test.o
+OBJS = $(COBJS)
+INCLUDES = -I../hidapi -I/usr/local/include
+LDFLAGS = -L/usr/local/lib
+LIBS = -lusb -liconv -pthread
+
+
+# Console Test Program
+hidtest: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
+
+# Shared Libs
+libhidapi.so: $(COBJS)
+ $(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS)
+
+# Objects
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
+
+
+clean:
+ rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o
+
+.PHONY: clean libs
diff --git a/c/src/third-party/hidapi/libusb/Makefile.linux b/c/src/third-party/hidapi/libusb/Makefile.linux
new file mode 100644
index 000000000..4b338ec9b
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/Makefile.linux
@@ -0,0 +1,42 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidtest-libusb libs
+
+libs: libhidapi-libusb.so
+
+CC ?= gcc
+CFLAGS ?= -Wall -g -fpic
+
+LDFLAGS ?= -Wall -g
+
+COBJS_LIBUSB = hid.o
+COBJS = $(COBJS_LIBUSB) ../hidtest/test.o
+OBJS = $(COBJS)
+LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt -lpthread
+LIBS = $(LIBS_USB)
+INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
+
+
+# Console Test Program
+hidtest-libusb: $(COBJS)
+ $(CC) $(LDFLAGS) $^ $(LIBS_USB) -o $@
+
+# Shared Libs
+libhidapi-libusb.so: $(COBJS_LIBUSB)
+ $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
+
+# Objects
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
+
+
+clean:
+ rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o
+
+.PHONY: clean libs
diff --git a/c/src/third-party/hidapi/libusb/hid.c b/c/src/third-party/hidapi/libusb/hid.c
new file mode 100644
index 000000000..8a1ae645d
--- /dev/null
+++ b/c/src/third-party/hidapi/libusb/hid.c
@@ -0,0 +1,1558 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+ Linux Version - 6/2/2010
+ Libusb Version - 8/13/2010
+ FreeBSD Version - 11/1/2011
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ https://github.com/libusb/hidapi .
+********************************************************/
+
+#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
+
+/* C */
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Unix */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* GNU / LibUSB */
+#include
+#if !defined(__ANDROID__) && !defined(NO_ICONV)
+#include
+#endif
+
+#include "hidapi.h"
+
+#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__
+
+/* Barrier implementation because Android/Bionic don't have pthread_barrier.
+ This implementation came from Brent Priddy and was posted on
+ StackOverflow. It is used with his permission. */
+typedef int pthread_barrierattr_t;
+typedef struct pthread_barrier {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int count;
+ int trip_count;
+} pthread_barrier_t;
+
+static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
+{
+ if(count == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
+ return -1;
+ }
+ if(pthread_cond_init(&barrier->cond, 0) < 0) {
+ pthread_mutex_destroy(&barrier->mutex);
+ return -1;
+ }
+ barrier->trip_count = count;
+ barrier->count = 0;
+
+ return 0;
+}
+
+static int pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+ pthread_cond_destroy(&barrier->cond);
+ pthread_mutex_destroy(&barrier->mutex);
+ return 0;
+}
+
+static int pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+ pthread_mutex_lock(&barrier->mutex);
+ ++(barrier->count);
+ if(barrier->count >= barrier->trip_count)
+ {
+ barrier->count = 0;
+ pthread_cond_broadcast(&barrier->cond);
+ pthread_mutex_unlock(&barrier->mutex);
+ return 1;
+ }
+ else
+ {
+ pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+ pthread_mutex_unlock(&barrier->mutex);
+ return 0;
+ }
+}
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef DEBUG_PRINTF
+#define LOG(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define LOG(...) do {} while (0)
+#endif
+
+#ifndef __FreeBSD__
+#define DETACH_KERNEL_DRIVER
+#endif
+
+/* Uncomment to enable the retrieval of Usage and Usage Page in
+hid_enumerate(). Warning, on platforms different from FreeBSD
+this is very invasive as it requires the detach
+and re-attach of the kernel driver. See comments inside hid_enumerate().
+libusb HIDAPI programs are encouraged to use the interface number
+instead to differentiate between interfaces on a composite HID device. */
+/*#define INVASIVE_GET_USAGE*/
+
+/* Linked List of input reports received from the device. */
+struct input_report {
+ uint8_t *data;
+ size_t len;
+ struct input_report *next;
+};
+
+
+struct hid_device_ {
+ /* Handle to the actual device. */
+ libusb_device_handle *device_handle;
+
+ /* Endpoint information */
+ int input_endpoint;
+ int output_endpoint;
+ int input_ep_max_packet_size;
+
+ /* The interface number of the HID */
+ int interface;
+
+ /* Indexes of Strings */
+ int manufacturer_index;
+ int product_index;
+ int serial_index;
+
+ /* Whether blocking reads are used */
+ int blocking; /* boolean */
+
+ /* Read thread objects */
+ pthread_t thread;
+ pthread_mutex_t mutex; /* Protects input_reports */
+ pthread_cond_t condition;
+ pthread_barrier_t barrier; /* Ensures correct startup sequence */
+ int shutdown_thread;
+ int cancelled;
+ struct libusb_transfer *transfer;
+
+ /* List of received input reports. */
+ struct input_report *input_reports;
+
+ /* Was kernel driver detached by libusb */
+#ifdef DETACH_KERNEL_DRIVER
+ int is_driver_detached;
+#endif
+};
+
+static libusb_context *usb_context = NULL;
+
+uint16_t get_usb_code_for_current_locale(void);
+static int return_data(hid_device *dev, unsigned char *data, size_t length);
+
+static hid_device *new_hid_device(void)
+{
+ hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
+ dev->blocking = 1;
+
+ pthread_mutex_init(&dev->mutex, NULL);
+ pthread_cond_init(&dev->condition, NULL);
+ pthread_barrier_init(&dev->barrier, NULL, 2);
+
+ return dev;
+}
+
+static void free_hid_device(hid_device *dev)
+{
+ /* Clean up the thread objects */
+ pthread_barrier_destroy(&dev->barrier);
+ pthread_cond_destroy(&dev->condition);
+ pthread_mutex_destroy(&dev->mutex);
+
+ /* Free the device itself */
+ free(dev);
+}
+
+#if 0
+/*TODO: Implement this function on hidapi/libusb.. */
+static void register_error(hid_device *dev, const char *op)
+{
+
+}
+#endif
+
+#ifdef INVASIVE_GET_USAGE
+/* Get bytes from a HID Report Descriptor.
+ Only call with a num_bytes of 0, 1, 2, or 4. */
+static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur)
+{
+ /* Return if there aren't enough bytes. */
+ if (cur + num_bytes >= len)
+ return 0;
+
+ if (num_bytes == 0)
+ return 0;
+ else if (num_bytes == 1) {
+ return rpt[cur+1];
+ }
+ else if (num_bytes == 2) {
+ return (rpt[cur+2] * 256 + rpt[cur+1]);
+ }
+ else if (num_bytes == 4) {
+ return (rpt[cur+4] * 0x01000000 +
+ rpt[cur+3] * 0x00010000 +
+ rpt[cur+2] * 0x00000100 +
+ rpt[cur+1] * 0x00000001);
+ }
+ else
+ return 0;
+}
+
+/* Retrieves the device's Usage Page and Usage from the report
+ descriptor. The algorithm is simple, as it just returns the first
+ Usage and Usage Page that it finds in the descriptor.
+ The return value is 0 on success and -1 on failure. */
+static int get_usage(uint8_t *report_descriptor, size_t size,
+ unsigned short *usage_page, unsigned short *usage)
+{
+ unsigned int i = 0;
+ int size_code;
+ int data_len, key_size;
+ int usage_found = 0, usage_page_found = 0;
+
+ while (i < size) {
+ int key = report_descriptor[i];
+ int key_cmd = key & 0xfc;
+
+ //printf("key: %02hhx\n", key);
+
+ if ((key & 0xf0) == 0xf0) {
+ /* This is a Long Item. The next byte contains the
+ length of the data section (value) for this key.
+ See the HID specification, version 1.11, section
+ 6.2.2.3, titled "Long Items." */
+ if (i+1 < size)
+ data_len = report_descriptor[i+1];
+ else
+ data_len = 0; /* malformed report */
+ key_size = 3;
+ }
+ else {
+ /* This is a Short Item. The bottom two bits of the
+ key contain the size code for the data section
+ (value) for this key. Refer to the HID
+ specification, version 1.11, section 6.2.2.2,
+ titled "Short Items." */
+ size_code = key & 0x3;
+ switch (size_code) {
+ case 0:
+ case 1:
+ case 2:
+ data_len = size_code;
+ break;
+ case 3:
+ data_len = 4;
+ break;
+ default:
+ /* Can't ever happen since size_code is & 0x3 */
+ data_len = 0;
+ break;
+ };
+ key_size = 1;
+ }
+
+ if (key_cmd == 0x4) {
+ *usage_page = get_bytes(report_descriptor, size, data_len, i);
+ usage_page_found = 1;
+ //printf("Usage Page: %x\n", (uint32_t)*usage_page);
+ }
+ if (key_cmd == 0x8) {
+ *usage = get_bytes(report_descriptor, size, data_len, i);
+ usage_found = 1;
+ //printf("Usage: %x\n", (uint32_t)*usage);
+ }
+
+ if (usage_page_found && usage_found)
+ return 0; /* success */
+
+ /* Skip over this key and it's associated data */
+ i += data_len + key_size;
+ }
+
+ return -1; /* failure */
+}
+#endif /* INVASIVE_GET_USAGE */
+
+#if defined(__FreeBSD__) && __FreeBSD__ < 10
+/* The libusb version included in FreeBSD < 10 doesn't have this function. In
+ mainline libusb, it's inlined in libusb.h. This function will bear a striking
+ resemblance to that one, because there's about one way to code it.
+
+ Note that the data parameter is Unicode in UTF-16LE encoding.
+ Return value is the number of bytes in data, or LIBUSB_ERROR_*.
+ */
+static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
+ uint8_t descriptor_index, uint16_t lang_id,
+ unsigned char *data, int length)
+{
+ return libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
+ LIBUSB_REQUEST_GET_DESCRIPTOR,
+ (LIBUSB_DT_STRING << 8) | descriptor_index,
+ lang_id, data, (uint16_t) length, 1000);
+}
+
+#endif
+
+
+/* Get the first language the device says it reports. This comes from
+ USB string #0. */
+static uint16_t get_first_language(libusb_device_handle *dev)
+{
+ uint16_t buf[32];
+ int len;
+
+ /* Get the string from libusb. */
+ len = libusb_get_string_descriptor(dev,
+ 0x0, /* String ID */
+ 0x0, /* Language */
+ (unsigned char*)buf,
+ sizeof(buf));
+ if (len < 4)
+ return 0x0;
+
+ return buf[1]; /* First two bytes are len and descriptor type. */
+}
+
+static int is_language_supported(libusb_device_handle *dev, uint16_t lang)
+{
+ uint16_t buf[32];
+ int len;
+ int i;
+
+ /* Get the string from libusb. */
+ len = libusb_get_string_descriptor(dev,
+ 0x0, /* String ID */
+ 0x0, /* Language */
+ (unsigned char*)buf,
+ sizeof(buf));
+ if (len < 4)
+ return 0x0;
+
+
+ len /= 2; /* language IDs are two-bytes each. */
+ /* Start at index 1 because there are two bytes of protocol data. */
+ for (i = 1; i < len; i++) {
+ if (buf[i] == lang)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* This function returns a newly allocated wide string containing the USB
+ device string numbered by the index. The returned string must be freed
+ by using free(). */
+static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
+{
+ char buf[512];
+ int len;
+ wchar_t *str = NULL;
+
+#if !defined(__ANDROID__) && !defined(NO_ICONV) /* we don't use iconv on Android, or when it is explicitly disabled */
+ wchar_t wbuf[256];
+ /* iconv variables */
+ iconv_t ic;
+ size_t inbytes;
+ size_t outbytes;
+ size_t res;
+ char *inptr;
+ char *outptr;
+#endif
+
+ /* Determine which language to use. */
+ uint16_t lang;
+ lang = get_usb_code_for_current_locale();
+ if (!is_language_supported(dev, lang))
+ lang = get_first_language(dev);
+
+ /* Get the string from libusb. */
+ len = libusb_get_string_descriptor(dev,
+ idx,
+ lang,
+ (unsigned char*)buf,
+ sizeof(buf));
+ if (len < 0)
+ return NULL;
+
+#if defined(__ANDROID__) || defined(NO_ICONV)
+
+ /* Bionic does not have iconv support nor wcsdup() function, so it
+ has to be done manually. The following code will only work for
+ code points that can be represented as a single UTF-16 character,
+ and will incorrectly convert any code points which require more
+ than one UTF-16 character.
+
+ Skip over the first character (2-bytes). */
+ len -= 2;
+ str = (wchar_t*) malloc((len / 2 + 1) * sizeof(wchar_t));
+ int i;
+ for (i = 0; i < len / 2; i++) {
+ str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
+ }
+ str[len / 2] = 0x00000000;
+
+#else
+
+ /* buf does not need to be explicitly NULL-terminated because
+ it is only passed into iconv() which does not need it. */
+
+ /* Initialize iconv. */
+ ic = iconv_open("WCHAR_T", "UTF-16LE");
+ if (ic == (iconv_t)-1) {
+ LOG("iconv_open() failed\n");
+ return NULL;
+ }
+
+ /* Convert to native wchar_t (UTF-32 on glibc/BSD systems).
+ Skip the first character (2-bytes). */
+ inptr = buf+2;
+ inbytes = len-2;
+ outptr = (char*) wbuf;
+ outbytes = sizeof(wbuf);
+ res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes);
+ if (res == (size_t)-1) {
+ LOG("iconv() failed\n");
+ goto err;
+ }
+
+ /* Write the terminating NULL. */
+ wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000;
+ if (outbytes >= sizeof(wbuf[0]))
+ *((wchar_t*)outptr) = 0x00000000;
+
+ /* Allocate and copy the string. */
+ str = wcsdup(wbuf);
+
+err:
+ iconv_close(ic);
+
+#endif
+
+ return str;
+}
+
+static char *make_path(libusb_device *dev, int interface_number)
+{
+ char str[64];
+ snprintf(str, sizeof(str), "%04x:%04x:%02x",
+ libusb_get_bus_number(dev),
+ libusb_get_device_address(dev),
+ interface_number);
+ str[sizeof(str)-1] = '\0';
+
+ return strdup(str);
+}
+
+
+int HID_API_EXPORT hid_init(void)
+{
+ if (!usb_context) {
+ const char *locale;
+
+ /* Init Libusb */
+ if (libusb_init(&usb_context))
+ return -1;
+
+ /* Set the locale if it's not set. */
+ locale = setlocale(LC_CTYPE, NULL);
+ if (!locale)
+ setlocale(LC_CTYPE, "");
+ }
+
+ return 0;
+}
+
+int HID_API_EXPORT hid_exit(void)
+{
+ if (usb_context) {
+ libusb_exit(usb_context);
+ usb_context = NULL;
+ }
+
+ return 0;
+}
+
+struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ libusb_device **devs;
+ libusb_device *dev;
+ libusb_device_handle *handle;
+ ssize_t num_devs;
+ int i = 0;
+
+ struct hid_device_info *root = NULL; /* return object */
+ struct hid_device_info *cur_dev = NULL;
+
+ if(hid_init() < 0)
+ return NULL;
+
+ num_devs = libusb_get_device_list(usb_context, &devs);
+ if (num_devs < 0)
+ return NULL;
+ while ((dev = devs[i++]) != NULL) {
+ struct libusb_device_descriptor desc;
+ struct libusb_config_descriptor *conf_desc = NULL;
+ int j, k;
+ int interface_num = 0;
+
+ int res = libusb_get_device_descriptor(dev, &desc);
+ unsigned short dev_vid = desc.idVendor;
+ unsigned short dev_pid = desc.idProduct;
+
+ res = libusb_get_active_config_descriptor(dev, &conf_desc);
+ if (res < 0)
+ libusb_get_config_descriptor(dev, 0, &conf_desc);
+ if (conf_desc) {
+ for (j = 0; j < conf_desc->bNumInterfaces; j++) {
+ const struct libusb_interface *intf = &conf_desc->interface[j];
+ for (k = 0; k < intf->num_altsetting; k++) {
+ const struct libusb_interface_descriptor *intf_desc;
+ intf_desc = &intf->altsetting[k];
+ if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
+ interface_num = intf_desc->bInterfaceNumber;
+
+ /* Check the VID/PID against the arguments */
+ if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
+ (product_id == 0x0 || product_id == dev_pid)) {
+ struct hid_device_info *tmp;
+
+ /* VID/PID match. Create the record. */
+ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
+ if (cur_dev) {
+ cur_dev->next = tmp;
+ }
+ else {
+ root = tmp;
+ }
+ cur_dev = tmp;
+
+ /* Fill out the record */
+ cur_dev->next = NULL;
+ cur_dev->path = make_path(dev, interface_num);
+
+ res = libusb_open(dev, &handle);
+
+ if (res >= 0) {
+ /* Serial Number */
+ if (desc.iSerialNumber > 0)
+ cur_dev->serial_number =
+ get_usb_string(handle, desc.iSerialNumber);
+
+ /* Manufacturer and Product strings */
+ if (desc.iManufacturer > 0)
+ cur_dev->manufacturer_string =
+ get_usb_string(handle, desc.iManufacturer);
+ if (desc.iProduct > 0)
+ cur_dev->product_string =
+ get_usb_string(handle, desc.iProduct);
+
+#ifdef INVASIVE_GET_USAGE
+{
+ /*
+ This section is removed because it is too
+ invasive on the system. Getting a Usage Page
+ and Usage requires parsing the HID Report
+ descriptor. Getting a HID Report descriptor
+ involves claiming the interface. Claiming the
+ interface involves detaching the kernel driver.
+ Detaching the kernel driver is hard on the system
+ because it will unclaim interfaces (if another
+ app has them claimed) and the re-attachment of
+ the driver will sometimes change /dev entry names.
+ It is for these reasons that this section is
+ #if 0. For composite devices, use the interface
+ field in the hid_device_info struct to distinguish
+ between interfaces. */
+ unsigned char data[256];
+#ifdef DETACH_KERNEL_DRIVER
+ int detached = 0;
+ /* Usage Page and Usage */
+ res = libusb_kernel_driver_active(handle, interface_num);
+ if (res == 1) {
+ res = libusb_detach_kernel_driver(handle, interface_num);
+ if (res < 0)
+ LOG("Couldn't detach kernel driver, even though a kernel driver was attached.");
+ else
+ detached = 1;
+ }
+#endif
+ res = libusb_claim_interface(handle, interface_num);
+ if (res >= 0) {
+ /* Get the HID Report Descriptor. */
+ res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000);
+ if (res >= 0) {
+ unsigned short page=0, usage=0;
+ /* Parse the usage and usage page
+ out of the report descriptor. */
+ get_usage(data, res, &page, &usage);
+ cur_dev->usage_page = page;
+ cur_dev->usage = usage;
+ }
+ else
+ LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res);
+
+ /* Release the interface */
+ res = libusb_release_interface(handle, interface_num);
+ if (res < 0)
+ LOG("Can't release the interface.\n");
+ }
+ else
+ LOG("Can't claim interface %d\n", res);
+#ifdef DETACH_KERNEL_DRIVER
+ /* Re-attach kernel driver if necessary. */
+ if (detached) {
+ res = libusb_attach_kernel_driver(handle, interface_num);
+ if (res < 0)
+ LOG("Couldn't re-attach kernel driver.\n");
+ }
+#endif
+}
+#endif /* INVASIVE_GET_USAGE */
+
+ libusb_close(handle);
+ }
+ /* VID/PID */
+ cur_dev->vendor_id = dev_vid;
+ cur_dev->product_id = dev_pid;
+
+ /* Release Number */
+ cur_dev->release_number = desc.bcdDevice;
+
+ /* Interface Number */
+ cur_dev->interface_number = interface_num;
+ }
+ }
+ } /* altsettings */
+ } /* interfaces */
+ libusb_free_config_descriptor(conf_desc);
+ }
+ }
+
+ libusb_free_device_list(devs, 1);
+
+ return root;
+}
+
+void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
+{
+ struct hid_device_info *d = devs;
+ while (d) {
+ struct hid_device_info *next = d->next;
+ free(d->path);
+ free(d->serial_number);
+ free(d->manufacturer_string);
+ free(d->product_string);
+ free(d);
+ d = next;
+ }
+}
+
+hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+ struct hid_device_info *devs, *cur_dev;
+ const char *path_to_open = NULL;
+ hid_device *handle = NULL;
+
+ devs = hid_enumerate(vendor_id, product_id);
+ cur_dev = devs;
+ while (cur_dev) {
+ if (cur_dev->vendor_id == vendor_id &&
+ cur_dev->product_id == product_id) {
+ if (serial_number) {
+ if (cur_dev->serial_number &&
+ wcscmp(serial_number, cur_dev->serial_number) == 0) {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ else {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ cur_dev = cur_dev->next;
+ }
+
+ if (path_to_open) {
+ /* Open the device */
+ handle = hid_open_path(path_to_open);
+ }
+
+ hid_free_enumeration(devs);
+
+ return handle;
+}
+
+static void read_callback(struct libusb_transfer *transfer)
+{
+ hid_device *dev = transfer->user_data;
+ int res;
+
+ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
+
+ struct input_report *rpt = (struct input_report*) malloc(sizeof(*rpt));
+ rpt->data = (uint8_t*) malloc(transfer->actual_length);
+ memcpy(rpt->data, transfer->buffer, transfer->actual_length);
+ rpt->len = transfer->actual_length;
+ rpt->next = NULL;
+
+ pthread_mutex_lock(&dev->mutex);
+
+ /* Attach the new report object to the end of the list. */
+ if (dev->input_reports == NULL) {
+ /* The list is empty. Put it at the root. */
+ dev->input_reports = rpt;
+ pthread_cond_signal(&dev->condition);
+ }
+ else {
+ /* Find the end of the list and attach. */
+ struct input_report *cur = dev->input_reports;
+ int num_queued = 0;
+ while (cur->next != NULL) {
+ cur = cur->next;
+ num_queued++;
+ }
+ cur->next = rpt;
+
+ /* Pop one off if we've reached 30 in the queue. This
+ way we don't grow forever if the user never reads
+ anything from the device. */
+ if (num_queued > 30) {
+ return_data(dev, NULL, 0);
+ }
+ }
+ pthread_mutex_unlock(&dev->mutex);
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ return;
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ return;
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
+ //LOG("Timeout (normal)\n");
+ }
+ else {
+ LOG("Unknown transfer code: %d\n", transfer->status);
+ }
+
+ /* Re-submit the transfer object. */
+ res = libusb_submit_transfer(transfer);
+ if (res != 0) {
+ LOG("Unable to submit URB. libusb error code: %d\n", res);
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ }
+}
+
+
+static void *read_thread(void *param)
+{
+ hid_device *dev = param;
+ uint8_t *buf;
+ const size_t length = dev->input_ep_max_packet_size;
+
+ /* Set up the transfer object. */
+ buf = (uint8_t*) malloc(length);
+ dev->transfer = libusb_alloc_transfer(0);
+ libusb_fill_interrupt_transfer(dev->transfer,
+ dev->device_handle,
+ dev->input_endpoint,
+ buf,
+ length,
+ read_callback,
+ dev,
+ 5000/*timeout*/);
+
+ /* Make the first submission. Further submissions are made
+ from inside read_callback() */
+ libusb_submit_transfer(dev->transfer);
+
+ /* Notify the main thread that the read thread is up and running. */
+ pthread_barrier_wait(&dev->barrier);
+
+ /* Handle all the events. */
+ while (!dev->shutdown_thread) {
+ int res;
+ res = libusb_handle_events(usb_context);
+ if (res < 0) {
+ /* There was an error. */
+ LOG("read_thread(): libusb reports error # %d\n", res);
+
+ /* Break out of this loop only on fatal error.*/
+ if (res != LIBUSB_ERROR_BUSY &&
+ res != LIBUSB_ERROR_TIMEOUT &&
+ res != LIBUSB_ERROR_OVERFLOW &&
+ res != LIBUSB_ERROR_INTERRUPTED) {
+ break;
+ }
+ }
+ }
+
+ /* Cancel any transfer that may be pending. This call will fail
+ if no transfers are pending, but that's OK. */
+ libusb_cancel_transfer(dev->transfer);
+
+ while (!dev->cancelled)
+ libusb_handle_events_completed(usb_context, &dev->cancelled);
+
+ /* Now that the read thread is stopping, Wake any threads which are
+ waiting on data (in hid_read_timeout()). Do this under a mutex to
+ make sure that a thread which is about to go to sleep waiting on
+ the condition actually will go to sleep before the condition is
+ signaled. */
+ pthread_mutex_lock(&dev->mutex);
+ pthread_cond_broadcast(&dev->condition);
+ pthread_mutex_unlock(&dev->mutex);
+
+ /* The dev->transfer->buffer and dev->transfer objects are cleaned up
+ in hid_close(). They are not cleaned up here because this thread
+ could end either due to a disconnect or due to a user
+ call to hid_close(). In both cases the objects can be safely
+ cleaned up after the call to pthread_join() (in hid_close()), but
+ since hid_close() calls libusb_cancel_transfer(), on these objects,
+ they can not be cleaned up here. */
+
+ return NULL;
+}
+
+
+hid_device * HID_API_EXPORT hid_open_path(const char *path)
+{
+ hid_device *dev = NULL;
+
+ libusb_device **devs;
+ libusb_device *usb_dev;
+ int res;
+ int d = 0;
+ int good_open = 0;
+
+ if(hid_init() < 0)
+ return NULL;
+
+ dev = new_hid_device();
+
+ libusb_get_device_list(usb_context, &devs);
+ while ((usb_dev = devs[d++]) != NULL) {
+ struct libusb_device_descriptor desc;
+ struct libusb_config_descriptor *conf_desc = NULL;
+ int i,j,k;
+ libusb_get_device_descriptor(usb_dev, &desc);
+
+ if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
+ continue;
+ for (j = 0; j < conf_desc->bNumInterfaces; j++) {
+ const struct libusb_interface *intf = &conf_desc->interface[j];
+ for (k = 0; k < intf->num_altsetting; k++) {
+ const struct libusb_interface_descriptor *intf_desc;
+ intf_desc = &intf->altsetting[k];
+ if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
+ char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
+ if (!strcmp(dev_path, path)) {
+ /* Matched Paths. Open this device */
+
+ /* OPEN HERE */
+ res = libusb_open(usb_dev, &dev->device_handle);
+ if (res < 0) {
+ LOG("can't open device\n");
+ free(dev_path);
+ break;
+ }
+ good_open = 1;
+#ifdef DETACH_KERNEL_DRIVER
+ /* Detach the kernel driver, but only if the
+ device is managed by the kernel */
+ dev->is_driver_detached = 0;
+ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
+ res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
+ if (res < 0) {
+ libusb_close(dev->device_handle);
+ LOG("Unable to detach Kernel Driver\n");
+ free(dev_path);
+ good_open = 0;
+ break;
+ }
+ else {
+ dev->is_driver_detached = 1;
+ LOG("Driver successfully detached from kernel.\n");
+ }
+ }
+#endif
+ res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
+ if (res < 0) {
+ LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
+ free(dev_path);
+ libusb_close(dev->device_handle);
+ good_open = 0;
+ break;
+ }
+
+ /* Store off the string descriptor indexes */
+ dev->manufacturer_index = desc.iManufacturer;
+ dev->product_index = desc.iProduct;
+ dev->serial_index = desc.iSerialNumber;
+
+ /* Store off the interface number */
+ dev->interface = intf_desc->bInterfaceNumber;
+
+ /* Find the INPUT and OUTPUT endpoints. An
+ OUTPUT endpoint is not required. */
+ for (i = 0; i < intf_desc->bNumEndpoints; i++) {
+ const struct libusb_endpoint_descriptor *ep
+ = &intf_desc->endpoint[i];
+
+ /* Determine the type and direction of this
+ endpoint. */
+ int is_interrupt =
+ (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
+ == LIBUSB_TRANSFER_TYPE_INTERRUPT;
+ int is_output =
+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
+ == LIBUSB_ENDPOINT_OUT;
+ int is_input =
+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
+ == LIBUSB_ENDPOINT_IN;
+
+ /* Decide whether to use it for input or output. */
+ if (dev->input_endpoint == 0 &&
+ is_interrupt && is_input) {
+ /* Use this endpoint for INPUT */
+ dev->input_endpoint = ep->bEndpointAddress;
+ dev->input_ep_max_packet_size = ep->wMaxPacketSize;
+ }
+ if (dev->output_endpoint == 0 &&
+ is_interrupt && is_output) {
+ /* Use this endpoint for OUTPUT */
+ dev->output_endpoint = ep->bEndpointAddress;
+ }
+ }
+
+ pthread_create(&dev->thread, NULL, read_thread, dev);
+
+ /* Wait here for the read thread to be initialized. */
+ pthread_barrier_wait(&dev->barrier);
+
+ }
+ free(dev_path);
+ }
+ }
+ }
+ libusb_free_config_descriptor(conf_desc);
+
+ }
+
+ libusb_free_device_list(devs, 1);
+
+ /* If we have a good handle, return it. */
+ if (good_open) {
+ return dev;
+ }
+ else {
+ /* Unable to open any devices. */
+ free_hid_device(dev);
+ return NULL;
+ }
+}
+
+
+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int res;
+ int report_number = data[0];
+ int skipped_report_id = 0;
+
+ if (report_number == 0x0) {
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+
+
+ if (dev->output_endpoint <= 0) {
+ /* No interrupt out endpoint. Use the Control Endpoint */
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
+ 0x09/*HID Set_Report*/,
+ (2/*HID output*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ length++;
+
+ return length;
+ }
+ else {
+ /* Use the interrupt out endpoint */
+ int actual_length;
+ res = libusb_interrupt_transfer(dev->device_handle,
+ dev->output_endpoint,
+ (unsigned char*)data,
+ length,
+ &actual_length, 1000);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ actual_length++;
+
+ return actual_length;
+ }
+}
+
+/* Helper function, to simplify hid_read().
+ This should be called with dev->mutex locked. */
+static int return_data(hid_device *dev, unsigned char *data, size_t length)
+{
+ /* Copy the data out of the linked list item (rpt) into the
+ return buffer (data), and delete the liked list item. */
+ struct input_report *rpt = dev->input_reports;
+ size_t len = (length < rpt->len)? length: rpt->len;
+ if (len > 0)
+ memcpy(data, rpt->data, len);
+ dev->input_reports = rpt->next;
+ free(rpt->data);
+ free(rpt);
+ return len;
+}
+
+static void cleanup_mutex(void *param)
+{
+ hid_device *dev = param;
+ pthread_mutex_unlock(&dev->mutex);
+}
+
+
+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+ int bytes_read = -1;
+
+#if 0
+ int transferred;
+ int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
+ LOG("transferred: %d\n", transferred);
+ return transferred;
+#endif
+
+ pthread_mutex_lock(&dev->mutex);
+ pthread_cleanup_push(&cleanup_mutex, dev);
+
+ /* There's an input report queued up. Return it. */
+ if (dev->input_reports) {
+ /* Return the first one */
+ bytes_read = return_data(dev, data, length);
+ goto ret;
+ }
+
+ if (dev->shutdown_thread) {
+ /* This means the device has been disconnected.
+ An error code of -1 should be returned. */
+ bytes_read = -1;
+ goto ret;
+ }
+
+ if (milliseconds == -1) {
+ /* Blocking */
+ while (!dev->input_reports && !dev->shutdown_thread) {
+ pthread_cond_wait(&dev->condition, &dev->mutex);
+ }
+ if (dev->input_reports) {
+ bytes_read = return_data(dev, data, length);
+ }
+ }
+ else if (milliseconds > 0) {
+ /* Non-blocking, but called with timeout. */
+ int res;
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += milliseconds / 1000;
+ ts.tv_nsec += (milliseconds % 1000) * 1000000;
+ if (ts.tv_nsec >= 1000000000L) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
+ }
+
+ while (!dev->input_reports && !dev->shutdown_thread) {
+ res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
+ if (res == 0) {
+ if (dev->input_reports) {
+ bytes_read = return_data(dev, data, length);
+ break;
+ }
+
+ /* If we're here, there was a spurious wake up
+ or the read thread was shutdown. Run the
+ loop again (ie: don't break). */
+ }
+ else if (res == ETIMEDOUT) {
+ /* Timed out. */
+ bytes_read = 0;
+ break;
+ }
+ else {
+ /* Error. */
+ bytes_read = -1;
+ break;
+ }
+ }
+ }
+ else {
+ /* Purely non-blocking */
+ bytes_read = 0;
+ }
+
+ret:
+ pthread_mutex_unlock(&dev->mutex);
+ pthread_cleanup_pop(0);
+
+ return bytes_read;
+}
+
+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+ return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0);
+}
+
+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+ dev->blocking = !nonblock;
+
+ return 0;
+}
+
+
+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int res = -1;
+ int skipped_report_id = 0;
+ int report_number = data[0];
+
+ if (report_number == 0x0) {
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
+ 0x09/*HID set_report*/,
+ (3/*HID feature*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ /* Account for the report ID */
+ if (skipped_report_id)
+ length++;
+
+ return length;
+}
+
+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ int res = -1;
+ int skipped_report_id = 0;
+ int report_number = data[0];
+
+ if (report_number == 0x0) {
+ /* Offset the return buffer by 1, so that the report ID
+ will remain in byte 0. */
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
+ 0x01/*HID get_report*/,
+ (3/*HID feature*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ res++;
+
+ return res;
+}
+
+int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ int res = -1;
+ int skipped_report_id = 0;
+ int report_number = data[0];
+
+ if (report_number == 0x0) {
+ /* Offset the return buffer by 1, so that the report ID
+ will remain in byte 0. */
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
+ 0x01/*HID get_report*/,
+ (1/*HID Input*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ res++;
+
+ return res;
+}
+
+void HID_API_EXPORT hid_close(hid_device *dev)
+{
+ if (!dev)
+ return;
+
+ /* Cause read_thread() to stop. */
+ dev->shutdown_thread = 1;
+ libusb_cancel_transfer(dev->transfer);
+
+ /* Wait for read_thread() to end. */
+ pthread_join(dev->thread, NULL);
+
+ /* Clean up the Transfer objects allocated in read_thread(). */
+ free(dev->transfer->buffer);
+ libusb_free_transfer(dev->transfer);
+
+ /* release the interface */
+ libusb_release_interface(dev->device_handle, dev->interface);
+
+ /* reattach the kernel driver if it was detached */
+#ifdef DETACH_KERNEL_DRIVER
+ if (dev->is_driver_detached) {
+ int res = libusb_attach_kernel_driver(dev->device_handle, dev->interface);
+ if (res < 0)
+ LOG("Failed to reattach the driver to kernel.\n");
+ }
+#endif
+
+ /* Close the handle */
+ libusb_close(dev->device_handle);
+
+ /* Clear out the queue of received reports. */
+ pthread_mutex_lock(&dev->mutex);
+ while (dev->input_reports) {
+ return_data(dev, NULL, 0);
+ }
+ pthread_mutex_unlock(&dev->mutex);
+
+ free_hid_device(dev);
+}
+
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->product_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->serial_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+ wchar_t *str;
+
+ str = get_usb_string(dev->device_handle, string_index);
+ if (str) {
+ wcsncpy(string, str, maxlen);
+ string[maxlen-1] = L'\0';
+ free(str);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
+{
+ return L"hid_error is not implemented yet";
+}
+
+
+struct lang_map_entry {
+ const char *name;
+ const char *string_code;
+ uint16_t usb_code;
+};
+
+#define LANG(name,code,usb_code) { name, code, usb_code }
+static struct lang_map_entry lang_map[] = {
+ LANG("Afrikaans", "af", 0x0436),
+ LANG("Albanian", "sq", 0x041C),
+ LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801),
+ LANG("Arabic - Bahrain", "ar_bh", 0x3C01),
+ LANG("Arabic - Algeria", "ar_dz", 0x1401),
+ LANG("Arabic - Egypt", "ar_eg", 0x0C01),
+ LANG("Arabic - Iraq", "ar_iq", 0x0801),
+ LANG("Arabic - Jordan", "ar_jo", 0x2C01),
+ LANG("Arabic - Kuwait", "ar_kw", 0x3401),
+ LANG("Arabic - Lebanon", "ar_lb", 0x3001),
+ LANG("Arabic - Libya", "ar_ly", 0x1001),
+ LANG("Arabic - Morocco", "ar_ma", 0x1801),
+ LANG("Arabic - Oman", "ar_om", 0x2001),
+ LANG("Arabic - Qatar", "ar_qa", 0x4001),
+ LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401),
+ LANG("Arabic - Syria", "ar_sy", 0x2801),
+ LANG("Arabic - Tunisia", "ar_tn", 0x1C01),
+ LANG("Arabic - Yemen", "ar_ye", 0x2401),
+ LANG("Armenian", "hy", 0x042B),
+ LANG("Azeri - Latin", "az_az", 0x042C),
+ LANG("Azeri - Cyrillic", "az_az", 0x082C),
+ LANG("Basque", "eu", 0x042D),
+ LANG("Belarusian", "be", 0x0423),
+ LANG("Bulgarian", "bg", 0x0402),
+ LANG("Catalan", "ca", 0x0403),
+ LANG("Chinese - China", "zh_cn", 0x0804),
+ LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04),
+ LANG("Chinese - Macau SAR", "zh_mo", 0x1404),
+ LANG("Chinese - Singapore", "zh_sg", 0x1004),
+ LANG("Chinese - Taiwan", "zh_tw", 0x0404),
+ LANG("Croatian", "hr", 0x041A),
+ LANG("Czech", "cs", 0x0405),
+ LANG("Danish", "da", 0x0406),
+ LANG("Dutch - Netherlands", "nl_nl", 0x0413),
+ LANG("Dutch - Belgium", "nl_be", 0x0813),
+ LANG("English - Australia", "en_au", 0x0C09),
+ LANG("English - Belize", "en_bz", 0x2809),
+ LANG("English - Canada", "en_ca", 0x1009),
+ LANG("English - Caribbean", "en_cb", 0x2409),
+ LANG("English - Ireland", "en_ie", 0x1809),
+ LANG("English - Jamaica", "en_jm", 0x2009),
+ LANG("English - New Zealand", "en_nz", 0x1409),
+ LANG("English - Philippines", "en_ph", 0x3409),
+ LANG("English - Southern Africa", "en_za", 0x1C09),
+ LANG("English - Trinidad", "en_tt", 0x2C09),
+ LANG("English - Great Britain", "en_gb", 0x0809),
+ LANG("English - United States", "en_us", 0x0409),
+ LANG("Estonian", "et", 0x0425),
+ LANG("Farsi", "fa", 0x0429),
+ LANG("Finnish", "fi", 0x040B),
+ LANG("Faroese", "fo", 0x0438),
+ LANG("French - France", "fr_fr", 0x040C),
+ LANG("French - Belgium", "fr_be", 0x080C),
+ LANG("French - Canada", "fr_ca", 0x0C0C),
+ LANG("French - Luxembourg", "fr_lu", 0x140C),
+ LANG("French - Switzerland", "fr_ch", 0x100C),
+ LANG("Gaelic - Ireland", "gd_ie", 0x083C),
+ LANG("Gaelic - Scotland", "gd", 0x043C),
+ LANG("German - Germany", "de_de", 0x0407),
+ LANG("German - Austria", "de_at", 0x0C07),
+ LANG("German - Liechtenstein", "de_li", 0x1407),
+ LANG("German - Luxembourg", "de_lu", 0x1007),
+ LANG("German - Switzerland", "de_ch", 0x0807),
+ LANG("Greek", "el", 0x0408),
+ LANG("Hebrew", "he", 0x040D),
+ LANG("Hindi", "hi", 0x0439),
+ LANG("Hungarian", "hu", 0x040E),
+ LANG("Icelandic", "is", 0x040F),
+ LANG("Indonesian", "id", 0x0421),
+ LANG("Italian - Italy", "it_it", 0x0410),
+ LANG("Italian - Switzerland", "it_ch", 0x0810),
+ LANG("Japanese", "ja", 0x0411),
+ LANG("Korean", "ko", 0x0412),
+ LANG("Latvian", "lv", 0x0426),
+ LANG("Lithuanian", "lt", 0x0427),
+ LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
+ LANG("Malay - Malaysia", "ms_my", 0x043E),
+ LANG("Malay – Brunei", "ms_bn", 0x083E),
+ LANG("Maltese", "mt", 0x043A),
+ LANG("Marathi", "mr", 0x044E),
+ LANG("Norwegian - Bokml", "no_no", 0x0414),
+ LANG("Norwegian - Nynorsk", "no_no", 0x0814),
+ LANG("Polish", "pl", 0x0415),
+ LANG("Portuguese - Portugal", "pt_pt", 0x0816),
+ LANG("Portuguese - Brazil", "pt_br", 0x0416),
+ LANG("Raeto-Romance", "rm", 0x0417),
+ LANG("Romanian - Romania", "ro", 0x0418),
+ LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818),
+ LANG("Russian", "ru", 0x0419),
+ LANG("Russian - Republic of Moldova", "ru_mo", 0x0819),
+ LANG("Sanskrit", "sa", 0x044F),
+ LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A),
+ LANG("Serbian - Latin", "sr_sp", 0x081A),
+ LANG("Setsuana", "tn", 0x0432),
+ LANG("Slovenian", "sl", 0x0424),
+ LANG("Slovak", "sk", 0x041B),
+ LANG("Sorbian", "sb", 0x042E),
+ LANG("Spanish - Spain (Traditional)", "es_es", 0x040A),
+ LANG("Spanish - Argentina", "es_ar", 0x2C0A),
+ LANG("Spanish - Bolivia", "es_bo", 0x400A),
+ LANG("Spanish - Chile", "es_cl", 0x340A),
+ LANG("Spanish - Colombia", "es_co", 0x240A),
+ LANG("Spanish - Costa Rica", "es_cr", 0x140A),
+ LANG("Spanish - Dominican Republic", "es_do", 0x1C0A),
+ LANG("Spanish - Ecuador", "es_ec", 0x300A),
+ LANG("Spanish - Guatemala", "es_gt", 0x100A),
+ LANG("Spanish - Honduras", "es_hn", 0x480A),
+ LANG("Spanish - Mexico", "es_mx", 0x080A),
+ LANG("Spanish - Nicaragua", "es_ni", 0x4C0A),
+ LANG("Spanish - Panama", "es_pa", 0x180A),
+ LANG("Spanish - Peru", "es_pe", 0x280A),
+ LANG("Spanish - Puerto Rico", "es_pr", 0x500A),
+ LANG("Spanish - Paraguay", "es_py", 0x3C0A),
+ LANG("Spanish - El Salvador", "es_sv", 0x440A),
+ LANG("Spanish - Uruguay", "es_uy", 0x380A),
+ LANG("Spanish - Venezuela", "es_ve", 0x200A),
+ LANG("Southern Sotho", "st", 0x0430),
+ LANG("Swahili", "sw", 0x0441),
+ LANG("Swedish - Sweden", "sv_se", 0x041D),
+ LANG("Swedish - Finland", "sv_fi", 0x081D),
+ LANG("Tamil", "ta", 0x0449),
+ LANG("Tatar", "tt", 0X0444),
+ LANG("Thai", "th", 0x041E),
+ LANG("Turkish", "tr", 0x041F),
+ LANG("Tsonga", "ts", 0x0431),
+ LANG("Ukrainian", "uk", 0x0422),
+ LANG("Urdu", "ur", 0x0420),
+ LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
+ LANG("Uzbek – Latin", "uz_uz", 0x0443),
+ LANG("Vietnamese", "vi", 0x042A),
+ LANG("Xhosa", "xh", 0x0434),
+ LANG("Yiddish", "yi", 0x043D),
+ LANG("Zulu", "zu", 0x0435),
+ LANG(NULL, NULL, 0x0),
+};
+
+uint16_t get_usb_code_for_current_locale(void)
+{
+ char *locale;
+ char search_string[64];
+ char *ptr;
+ struct lang_map_entry *lang;
+
+ /* Get the current locale. */
+ locale = setlocale(0, NULL);
+ if (!locale)
+ return 0x0;
+
+ /* Make a copy of the current locale string. */
+ strncpy(search_string, locale, sizeof(search_string));
+ search_string[sizeof(search_string)-1] = '\0';
+
+ /* Chop off the encoding part, and make it lower case. */
+ ptr = search_string;
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ if (*ptr == '.') {
+ *ptr = '\0';
+ break;
+ }
+ ptr++;
+ }
+
+ /* Find the entry which matches the string code of our locale. */
+ lang = lang_map;
+ while (lang->string_code) {
+ if (!strcmp(lang->string_code, search_string)) {
+ return lang->usb_code;
+ }
+ lang++;
+ }
+
+ /* There was no match. Find with just the language only. */
+ /* Chop off the variant. Chop it off at the '_'. */
+ ptr = search_string;
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ if (*ptr == '_') {
+ *ptr = '\0';
+ break;
+ }
+ ptr++;
+ }
+
+#if 0 /* TODO: Do we need this? */
+ /* Find the entry which matches the string code of our language. */
+ lang = lang_map;
+ while (lang->string_code) {
+ if (!strcmp(lang->string_code, search_string)) {
+ return lang->usb_code;
+ }
+ lang++;
+ }
+#endif
+
+ /* Found nothing. */
+ return 0x0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/c/src/third-party/hidapi/linux/.gitignore b/c/src/third-party/hidapi/linux/.gitignore
new file mode 100644
index 000000000..127bf37d9
--- /dev/null
+++ b/c/src/third-party/hidapi/linux/.gitignore
@@ -0,0 +1,18 @@
+Debug
+Release
+*.exp
+*.ilk
+*.lib
+*.suo
+*.vcproj.*
+*.ncb
+*.suo
+*.dll
+*.pdb
+*.o
+*.so
+hidtest-hidraw
+.deps
+.libs
+*.lo
+*.la
diff --git a/c/src/third-party/hidapi/linux/Makefile-manual b/c/src/third-party/hidapi/linux/Makefile-manual
new file mode 100644
index 000000000..81d28cf2c
--- /dev/null
+++ b/c/src/third-party/hidapi/linux/Makefile-manual
@@ -0,0 +1,42 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidtest-hidraw libs
+
+libs: libhidapi-hidraw.so
+
+CC ?= gcc
+CFLAGS ?= -Wall -g -fpic
+
+LDFLAGS ?= -Wall -g
+
+
+COBJS = hid.o ../hidtest/test.o
+OBJS = $(COBJS)
+LIBS_UDEV = `pkg-config libudev --libs` -lrt
+LIBS = $(LIBS_UDEV)
+INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags`
+
+
+# Console Test Program
+hidtest-hidraw: $(COBJS)
+ $(CC) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@
+
+# Shared Libs
+libhidapi-hidraw.so: $(COBJS)
+ $(CC) $(LDFLAGS) $(LIBS_UDEV) -shared -fpic -Wl,-soname,$@.0 $^ -o $@
+
+# Objects
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@
+
+
+clean:
+ rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so $(COBJS)
+
+.PHONY: clean libs
diff --git a/c/src/third-party/hidapi/linux/Makefile.am b/c/src/third-party/hidapi/linux/Makefile.am
new file mode 100644
index 000000000..230eeb75a
--- /dev/null
+++ b/c/src/third-party/hidapi/linux/Makefile.am
@@ -0,0 +1,10 @@
+lib_LTLIBRARIES = libhidapi-hidraw.la
+libhidapi_hidraw_la_SOURCES = hid.c
+libhidapi_hidraw_la_LDFLAGS = $(LTLDFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_HIDRAW)
+libhidapi_hidraw_la_LIBADD = $(LIBS_HIDRAW)
+
+hdrdir = $(includedir)/hidapi
+hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
+
+EXTRA_DIST = Makefile-manual
diff --git a/c/src/third-party/hidapi/linux/hid.c b/c/src/third-party/hidapi/linux/hid.c
new file mode 100644
index 000000000..07ab3e17a
--- /dev/null
+++ b/c/src/third-party/hidapi/linux/hid.c
@@ -0,0 +1,848 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+ Linux Version - 6/2/2009
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ https://github.com/libusb/hidapi .
+********************************************************/
+
+/* C */
+#include
+#include
+#include
+#include
+#include
+
+/* Unix */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Linux */
+#include
+#include
+#include
+#include
+
+#include "hidapi.h"
+
+
+/* USB HID device property names */
+const char *device_string_names[] = {
+ "manufacturer",
+ "product",
+ "serial",
+};
+
+/* Symbolic names for the properties above */
+enum device_string_id {
+ DEVICE_STRING_MANUFACTURER,
+ DEVICE_STRING_PRODUCT,
+ DEVICE_STRING_SERIAL,
+
+ DEVICE_STRING_COUNT,
+};
+
+struct hid_device_ {
+ int device_handle;
+ int blocking;
+ int uses_numbered_reports;
+ wchar_t *last_error_str;
+};
+
+/* Global error message that is not specific to a device, e.g. for
+ hid_open(). It is thread-local like errno. */
+__thread wchar_t *last_global_error_str = NULL;
+
+static hid_device *new_hid_device(void)
+{
+ hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
+ dev->device_handle = -1;
+ dev->blocking = 1;
+ dev->uses_numbered_reports = 0;
+ dev->last_error_str = NULL;
+
+ return dev;
+}
+
+
+/* The caller must free the returned string with free(). */
+static wchar_t *utf8_to_wchar_t(const char *utf8)
+{
+ wchar_t *ret = NULL;
+
+ if (utf8) {
+ size_t wlen = mbstowcs(NULL, utf8, 0);
+ if ((size_t) -1 == wlen) {
+ return wcsdup(L"");
+ }
+ ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t));
+ mbstowcs(ret, utf8, wlen+1);
+ ret[wlen] = 0x0000;
+ }
+
+ return ret;
+}
+
+
+/* Set the last global error to be reported by hid_error(NULL).
+ * The given error message will be copied (and decoded according to the
+ * currently locale, so do not pass in string constants).
+ * The last stored global error message is freed.
+ * Use register_global_error(NULL) to indicate "no error". */
+static void register_global_error(const char *msg)
+{
+ if (last_global_error_str)
+ free(last_global_error_str);
+
+ last_global_error_str = utf8_to_wchar_t(msg);
+}
+
+
+/* Set the last error for a device to be reported by hid_error(device).
+ * The given error message will be copied (and decoded according to the
+ * currently locale, so do not pass in string constants).
+ * The last stored global error message is freed.
+ * Use register_device_error(device, NULL) to indicate "no error". */
+static void register_device_error(hid_device *dev, const char *msg)
+{
+ if (dev->last_error_str)
+ free(dev->last_error_str);
+
+ dev->last_error_str = utf8_to_wchar_t(msg);
+}
+
+/* See register_device_error, but you can pass a format string into this function. */
+static void register_device_error_format(hid_device *dev, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+
+ char msg[100];
+ vsnprintf(msg, sizeof(msg), format, args);
+
+ va_end(args);
+
+ register_device_error(dev, msg);
+}
+
+/* Get an attribute value from a udev_device and return it as a whar_t
+ string. The returned string must be freed with free() when done.*/
+static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
+{
+ return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
+}
+
+/* uses_numbered_reports() returns 1 if report_descriptor describes a device
+ which contains numbered reports. */
+static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
+ unsigned int i = 0;
+ int size_code;
+ int data_len, key_size;
+
+ while (i < size) {
+ int key = report_descriptor[i];
+
+ /* Check for the Report ID key */
+ if (key == 0x85/*Report ID*/) {
+ /* This device has a Report ID, which means it uses
+ numbered reports. */
+ return 1;
+ }
+
+ //printf("key: %02hhx\n", key);
+
+ if ((key & 0xf0) == 0xf0) {
+ /* This is a Long Item. The next byte contains the
+ length of the data section (value) for this key.
+ See the HID specification, version 1.11, section
+ 6.2.2.3, titled "Long Items." */
+ if (i+1 < size)
+ data_len = report_descriptor[i+1];
+ else
+ data_len = 0; /* malformed report */
+ key_size = 3;
+ }
+ else {
+ /* This is a Short Item. The bottom two bits of the
+ key contain the size code for the data section
+ (value) for this key. Refer to the HID
+ specification, version 1.11, section 6.2.2.2,
+ titled "Short Items." */
+ size_code = key & 0x3;
+ switch (size_code) {
+ case 0:
+ case 1:
+ case 2:
+ data_len = size_code;
+ break;
+ case 3:
+ data_len = 4;
+ break;
+ default:
+ /* Can't ever happen since size_code is & 0x3 */
+ data_len = 0;
+ break;
+ };
+ key_size = 1;
+ }
+
+ /* Skip over this key and it's associated data */
+ i += data_len + key_size;
+ }
+
+ /* Didn't find a Report ID key. Device doesn't use numbered reports. */
+ return 0;
+}
+
+/*
+ * The caller is responsible for free()ing the (newly-allocated) character
+ * strings pointed to by serial_number_utf8 and product_name_utf8 after use.
+ */
+static int
+parse_uevent_info(const char *uevent, int *bus_type,
+ unsigned short *vendor_id, unsigned short *product_id,
+ char **serial_number_utf8, char **product_name_utf8)
+{
+ char *tmp = strdup(uevent);
+ char *saveptr = NULL;
+ char *line;
+ char *key;
+ char *value;
+
+ int found_id = 0;
+ int found_serial = 0;
+ int found_name = 0;
+
+ line = strtok_r(tmp, "\n", &saveptr);
+ while (line != NULL) {
+ /* line: "KEY=value" */
+ key = line;
+ value = strchr(line, '=');
+ if (!value) {
+ goto next_line;
+ }
+ *value = '\0';
+ value++;
+
+ if (strcmp(key, "HID_ID") == 0) {
+ /**
+ * type vendor product
+ * HID_ID=0003:000005AC:00008242
+ **/
+ int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id);
+ if (ret == 3) {
+ found_id = 1;
+ }
+ } else if (strcmp(key, "HID_NAME") == 0) {
+ /* The caller has to free the product name */
+ *product_name_utf8 = strdup(value);
+ found_name = 1;
+ } else if (strcmp(key, "HID_UNIQ") == 0) {
+ /* The caller has to free the serial number */
+ *serial_number_utf8 = strdup(value);
+ found_serial = 1;
+ }
+
+next_line:
+ line = strtok_r(NULL, "\n", &saveptr);
+ }
+
+ free(tmp);
+ return (found_id && found_name && found_serial);
+}
+
+
+static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen)
+{
+ struct udev *udev;
+ struct udev_device *udev_dev, *parent, *hid_dev;
+ struct stat s;
+ int ret = -1;
+ char *serial_number_utf8 = NULL;
+ char *product_name_utf8 = NULL;
+
+ /* Create the udev object */
+ udev = udev_new();
+ if (!udev) {
+ register_global_error("Couldn't create udev context");
+ return -1;
+ }
+
+ /* Get the dev_t (major/minor numbers) from the file handle. */
+ ret = fstat(dev->device_handle, &s);
+ if (-1 == ret)
+ return ret;
+ /* Open a udev device from the dev_t. 'c' means character device. */
+ udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev);
+ if (udev_dev) {
+ hid_dev = udev_device_get_parent_with_subsystem_devtype(
+ udev_dev,
+ "hid",
+ NULL);
+ if (hid_dev) {
+ unsigned short dev_vid;
+ unsigned short dev_pid;
+ int bus_type;
+ size_t retm;
+
+ ret = parse_uevent_info(
+ udev_device_get_sysattr_value(hid_dev, "uevent"),
+ &bus_type,
+ &dev_vid,
+ &dev_pid,
+ &serial_number_utf8,
+ &product_name_utf8);
+
+ if (bus_type == BUS_BLUETOOTH) {
+ switch (key) {
+ case DEVICE_STRING_MANUFACTURER:
+ wcsncpy(string, L"", maxlen);
+ ret = 0;
+ break;
+ case DEVICE_STRING_PRODUCT:
+ retm = mbstowcs(string, product_name_utf8, maxlen);
+ ret = (retm == (size_t)-1)? -1: 0;
+ break;
+ case DEVICE_STRING_SERIAL:
+ retm = mbstowcs(string, serial_number_utf8, maxlen);
+ ret = (retm == (size_t)-1)? -1: 0;
+ break;
+ case DEVICE_STRING_COUNT:
+ default:
+ ret = -1;
+ break;
+ }
+ }
+ else {
+ /* This is a USB device. Find its parent USB Device node. */
+ parent = udev_device_get_parent_with_subsystem_devtype(
+ udev_dev,
+ "usb",
+ "usb_device");
+ if (parent) {
+ const char *str;
+ const char *key_str = NULL;
+
+ if (key >= 0 && key < DEVICE_STRING_COUNT) {
+ key_str = device_string_names[key];
+ } else {
+ ret = -1;
+ goto end;
+ }
+
+ str = udev_device_get_sysattr_value(parent, key_str);
+ if (str) {
+ /* Convert the string from UTF-8 to wchar_t */
+ retm = mbstowcs(string, str, maxlen);
+ ret = (retm == (size_t)-1)? -1: 0;
+ goto end;
+ }
+ }
+ }
+ }
+ }
+
+end:
+ free(serial_number_utf8);
+ free(product_name_utf8);
+
+ udev_device_unref(udev_dev);
+ /* parent and hid_dev don't need to be (and can't be) unref'd.
+ I'm not sure why, but they'll throw double-free() errors. */
+ udev_unref(udev);
+
+ return ret;
+}
+
+int HID_API_EXPORT hid_init(void)
+{
+ const char *locale;
+
+ /* Set the locale if it's not set. */
+ locale = setlocale(LC_CTYPE, NULL);
+ if (!locale)
+ setlocale(LC_CTYPE, "");
+
+ return 0;
+}
+
+int HID_API_EXPORT hid_exit(void)
+{
+ /* Free global error message */
+ register_global_error(NULL);
+
+ return 0;
+}
+
+
+struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ struct udev *udev;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+
+ struct hid_device_info *root = NULL; /* return object */
+ struct hid_device_info *cur_dev = NULL;
+ struct hid_device_info *prev_dev = NULL; /* previous device */
+
+ hid_init();
+
+ /* Create the udev object */
+ udev = udev_new();
+ if (!udev) {
+ register_global_error("Couldn't create udev context");
+ return NULL;
+ }
+
+ /* Create a list of the devices in the 'hidraw' subsystem. */
+ enumerate = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(enumerate, "hidraw");
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+ /* For each item, see if it matches the vid/pid, and if so
+ create a udev_device record for it */
+ udev_list_entry_foreach(dev_list_entry, devices) {
+ const char *sysfs_path;
+ const char *dev_path;
+ const char *str;
+ struct udev_device *raw_dev; /* The device's hidraw udev node. */
+ struct udev_device *hid_dev; /* The device's HID udev node. */
+ struct udev_device *usb_dev; /* The device's USB udev node. */
+ struct udev_device *intf_dev; /* The device's interface (in the USB sense). */
+ unsigned short dev_vid;
+ unsigned short dev_pid;
+ char *serial_number_utf8 = NULL;
+ char *product_name_utf8 = NULL;
+ int bus_type;
+ int result;
+
+ /* Get the filename of the /sys entry for the device
+ and create a udev_device object (dev) representing it */
+ sysfs_path = udev_list_entry_get_name(dev_list_entry);
+ raw_dev = udev_device_new_from_syspath(udev, sysfs_path);
+ dev_path = udev_device_get_devnode(raw_dev);
+
+ hid_dev = udev_device_get_parent_with_subsystem_devtype(
+ raw_dev,
+ "hid",
+ NULL);
+
+ if (!hid_dev) {
+ /* Unable to find parent hid device. */
+ goto next;
+ }
+
+ result = parse_uevent_info(
+ udev_device_get_sysattr_value(hid_dev, "uevent"),
+ &bus_type,
+ &dev_vid,
+ &dev_pid,
+ &serial_number_utf8,
+ &product_name_utf8);
+
+ if (!result) {
+ /* parse_uevent_info() failed for at least one field. */
+ goto next;
+ }
+
+ if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
+ /* We only know how to handle USB and BT devices. */
+ goto next;
+ }
+
+ /* Check the VID/PID against the arguments */
+ if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
+ (product_id == 0x0 || product_id == dev_pid)) {
+ struct hid_device_info *tmp;
+
+ /* VID/PID match. Create the record. */
+ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
+ if (cur_dev) {
+ cur_dev->next = tmp;
+ }
+ else {
+ root = tmp;
+ }
+ prev_dev = cur_dev;
+ cur_dev = tmp;
+
+ /* Fill out the record */
+ cur_dev->next = NULL;
+ cur_dev->path = dev_path? strdup(dev_path): NULL;
+
+ /* VID/PID */
+ cur_dev->vendor_id = dev_vid;
+ cur_dev->product_id = dev_pid;
+
+ /* Serial Number */
+ cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8);
+
+ /* Release Number */
+ cur_dev->release_number = 0x0;
+
+ /* Interface Number */
+ cur_dev->interface_number = -1;
+
+ switch (bus_type) {
+ case BUS_USB:
+ /* The device pointed to by raw_dev contains information about
+ the hidraw device. In order to get information about the
+ USB device, get the parent device with the
+ subsystem/devtype pair of "usb"/"usb_device". This will
+ be several levels up the tree, but the function will find
+ it. */
+ usb_dev = udev_device_get_parent_with_subsystem_devtype(
+ raw_dev,
+ "usb",
+ "usb_device");
+
+ if (!usb_dev) {
+ /* Free this device */
+ free(cur_dev->serial_number);
+ free(cur_dev->path);
+ free(cur_dev);
+
+ /* Take it off the device list. */
+ if (prev_dev) {
+ prev_dev->next = NULL;
+ cur_dev = prev_dev;
+ }
+ else {
+ cur_dev = root = NULL;
+ }
+
+ goto next;
+ }
+
+ /* Manufacturer and Product strings */
+ cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]);
+ cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]);
+
+ /* Release Number */
+ str = udev_device_get_sysattr_value(usb_dev, "bcdDevice");
+ cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0;
+
+ /* Get a handle to the interface's udev node. */
+ intf_dev = udev_device_get_parent_with_subsystem_devtype(
+ raw_dev,
+ "usb",
+ "usb_interface");
+ if (intf_dev) {
+ str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber");
+ cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1;
+ }
+
+ break;
+
+ case BUS_BLUETOOTH:
+ /* Manufacturer and Product strings */
+ cur_dev->manufacturer_string = wcsdup(L"");
+ cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
+
+ break;
+
+ default:
+ /* Unknown device type - this should never happen, as we
+ * check for USB and Bluetooth devices above */
+ break;
+ }
+ }
+
+ next:
+ free(serial_number_utf8);
+ free(product_name_utf8);
+ udev_device_unref(raw_dev);
+ /* hid_dev, usb_dev and intf_dev don't need to be (and can't be)
+ unref()d. It will cause a double-free() error. I'm not
+ sure why. */
+ }
+ /* Free the enumerator and udev objects. */
+ udev_enumerate_unref(enumerate);
+ udev_unref(udev);
+
+ return root;
+}
+
+void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
+{
+ struct hid_device_info *d = devs;
+ while (d) {
+ struct hid_device_info *next = d->next;
+ free(d->path);
+ free(d->serial_number);
+ free(d->manufacturer_string);
+ free(d->product_string);
+ free(d);
+ d = next;
+ }
+}
+
+hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+ /* Set global error to none */
+ register_global_error(NULL);
+
+ struct hid_device_info *devs, *cur_dev;
+ const char *path_to_open = NULL;
+ hid_device *handle = NULL;
+
+ devs = hid_enumerate(vendor_id, product_id);
+ cur_dev = devs;
+ while (cur_dev) {
+ if (cur_dev->vendor_id == vendor_id &&
+ cur_dev->product_id == product_id) {
+ if (serial_number) {
+ if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ else {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ cur_dev = cur_dev->next;
+ }
+
+ if (path_to_open) {
+ /* Open the device */
+ handle = hid_open_path(path_to_open);
+ } else {
+ register_global_error("No such device");
+ }
+
+ hid_free_enumeration(devs);
+
+ return handle;
+}
+
+hid_device * HID_API_EXPORT hid_open_path(const char *path)
+{
+ /* Set global error to none */
+ register_global_error(NULL);
+
+ hid_device *dev = NULL;
+
+ hid_init();
+
+ dev = new_hid_device();
+
+ /* OPEN HERE */
+ dev->device_handle = open(path, O_RDWR);
+
+ /* If we have a good handle, return it. */
+ if (dev->device_handle > 0) {
+ /* Set device error to none */
+ register_device_error(dev, NULL);
+
+ /* Get the report descriptor */
+ int res, desc_size = 0;
+ struct hidraw_report_descriptor rpt_desc;
+
+ memset(&rpt_desc, 0x0, sizeof(rpt_desc));
+
+ /* Get Report Descriptor Size */
+ res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size);
+ if (res < 0)
+ register_device_error_format(dev, "ioctl (GRDESCSIZE): %s", strerror(errno));
+
+ /* Get Report Descriptor */
+ rpt_desc.size = desc_size;
+ res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc);
+ if (res < 0) {
+ register_device_error_format(dev, "ioctl (GRDESC): %s", strerror(errno));
+ } else {
+ /* Determine if this device uses numbered reports. */
+ dev->uses_numbered_reports =
+ uses_numbered_reports(rpt_desc.value,
+ rpt_desc.size);
+ }
+
+ return dev;
+ }
+ else {
+ /* Unable to open any devices. */
+ register_global_error(strerror(errno));
+ free(dev);
+ return NULL;
+ }
+}
+
+
+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int bytes_written;
+
+ bytes_written = write(dev->device_handle, data, length);
+
+ register_device_error(dev, (bytes_written == -1)? strerror(errno): NULL);
+
+ return bytes_written;
+}
+
+
+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+ /* Set device error to none */
+ register_device_error(dev, NULL);
+
+ int bytes_read;
+
+ if (milliseconds >= 0) {
+ /* Milliseconds is either 0 (non-blocking) or > 0 (contains
+ a valid timeout). In both cases we want to call poll()
+ and wait for data to arrive. Don't rely on non-blocking
+ operation (O_NONBLOCK) since some kernels don't seem to
+ properly report device disconnection through read() when
+ in non-blocking mode. */
+ int ret;
+ struct pollfd fds;
+
+ fds.fd = dev->device_handle;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ ret = poll(&fds, 1, milliseconds);
+ if (ret == 0) {
+ /* Timeout */
+ return ret;
+ }
+ if (ret == -1) {
+ /* Error */
+ register_device_error(dev, strerror(errno));
+ return ret;
+ }
+ else {
+ /* Check for errors on the file descriptor. This will
+ indicate a device disconnection. */
+ if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
+ // We cannot use strerror() here as no -1 was returned from poll().
+ return -1;
+ }
+ }
+
+ bytes_read = read(dev->device_handle, data, length);
+ if (bytes_read < 0) {
+ if (errno == EAGAIN || errno == EINPROGRESS)
+ bytes_read = 0;
+ else
+ register_device_error(dev, strerror(errno));
+ }
+
+ return bytes_read;
+}
+
+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+ return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
+}
+
+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+ /* Do all non-blocking in userspace using poll(), since it looks
+ like there's a bug in the kernel in some versions where
+ read() will not return -1 on disconnection of the USB device */
+
+ dev->blocking = !nonblock;
+ return 0; /* Success */
+}
+
+
+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int res;
+
+ res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data);
+ if (res < 0)
+ register_device_error_format(dev, "ioctl (SFEATURE): %s", strerror(errno));
+
+ return res;
+}
+
+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ int res;
+
+ res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data);
+ if (res < 0)
+ register_device_error_format(dev, "ioctl (GFEATURE): %s", strerror(errno));
+
+ return res;
+}
+
+// Not supported by Linux HidRaw yet
+int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ return -1;
+}
+
+void HID_API_EXPORT hid_close(hid_device *dev)
+{
+ if (!dev)
+ return;
+
+ int ret = close(dev->device_handle);
+
+ register_global_error((ret == -1)? strerror(errno): NULL);
+
+ /* Free the device error message */
+ register_device_error(dev, NULL);
+
+ free(dev);
+}
+
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+ return -1;
+}
+
+
+/* Passing in NULL means asking for the last global error message. */
+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
+{
+ if (dev) {
+ if (dev->last_error_str == NULL)
+ return L"Success";
+ return dev->last_error_str;
+ }
+
+ if (last_global_error_str == NULL)
+ return L"Success";
+ return last_global_error_str;
+}
diff --git a/c/src/third-party/hidapi/m4/.gitignore b/c/src/third-party/hidapi/m4/.gitignore
new file mode 100644
index 000000000..8f79b0204
--- /dev/null
+++ b/c/src/third-party/hidapi/m4/.gitignore
@@ -0,0 +1,5 @@
+# Ignore All, except pkg.m4, and of course this file.
+*
+!.gitignore
+!pkg.m4
+!ax_pthread.m4
diff --git a/c/src/third-party/hidapi/m4/ax_pthread.m4 b/c/src/third-party/hidapi/m4/ax_pthread.m4
new file mode 100644
index 000000000..d90de34d1
--- /dev/null
+++ b/c/src/third-party/hidapi/m4/ax_pthread.m4
@@ -0,0 +1,309 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also link it with them as well. e.g. you should link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threads programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson
+# Copyright (c) 2011 Daniel Richard G.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU 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 General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 18
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case ${host_os} in
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ darwin*)
+ ax_pthread_flags="-pthread $ax_pthread_flags"
+ ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
+ [int attr = $attr; return attr /* ; */])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case ${host_os} in
+ aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+ osf* | hpux*) flag="-D_REENTRANT";;
+ solaris*)
+ if test "$GCC" = "yes"; then
+ flag="-D_REENTRANT"
+ else
+ flag="-mt -D_REENTRANT"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ ax_cv_PTHREAD_PRIO_INHERIT, [
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+ AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with xlc_r or cc_r
+ if test x"$GCC" != xyes; then
+ AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+ else
+ PTHREAD_CC=$CC
+ fi
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/c/src/third-party/hidapi/m4/pkg.m4 b/c/src/third-party/hidapi/m4/pkg.m4
new file mode 100644
index 000000000..0048a3fa0
--- /dev/null
+++ b/c/src/third-party/hidapi/m4/pkg.m4
@@ -0,0 +1,157 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant .
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see .])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/c/src/third-party/hidapi/mac/.gitignore b/c/src/third-party/hidapi/mac/.gitignore
new file mode 100644
index 000000000..7cc3f0d0d
--- /dev/null
+++ b/c/src/third-party/hidapi/mac/.gitignore
@@ -0,0 +1,17 @@
+Debug
+Release
+*.exp
+*.ilk
+*.lib
+*.suo
+*.vcproj.*
+*.ncb
+*.suo
+*.dll
+*.pdb
+*.o
+hidapi-hidtest
+.deps
+.libs
+*.la
+*.lo
diff --git a/c/src/third-party/hidapi/mac/Makefile-manual b/c/src/third-party/hidapi/mac/Makefile-manual
new file mode 100644
index 000000000..30b50f5f9
--- /dev/null
+++ b/c/src/third-party/hidapi/mac/Makefile-manual
@@ -0,0 +1,27 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-07-03
+###########################################
+
+all: hidtest
+
+CC=gcc
+COBJS=hid.o ../hidtest/test.o
+OBJS=$(COBJS)
+CFLAGS+=-I../hidapi -Wall -g -c
+LIBS=-framework IOKit -framework CoreFoundation
+
+
+hidtest: $(OBJS)
+ $(CC) -Wall -g $^ $(LIBS) -o hidtest
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm -f *.o hidtest
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/mac/Makefile.am b/c/src/third-party/hidapi/mac/Makefile.am
new file mode 100644
index 000000000..23d96e08f
--- /dev/null
+++ b/c/src/third-party/hidapi/mac/Makefile.am
@@ -0,0 +1,9 @@
+lib_LTLIBRARIES = libhidapi.la
+libhidapi_la_SOURCES = hid.c
+libhidapi_la_LDFLAGS = $(LTLDFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
+
+hdrdir = $(includedir)/hidapi
+hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
+
+EXTRA_DIST = Makefile-manual
diff --git a/c/src/third-party/hidapi/mac/hid.c b/c/src/third-party/hidapi/mac/hid.c
new file mode 100644
index 000000000..31fab07bb
--- /dev/null
+++ b/c/src/third-party/hidapi/mac/hid.c
@@ -0,0 +1,1239 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 2010-07-03
+
+ Copyright 2010, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ https://github.com/libusb/hidapi .
+********************************************************/
+
+/* See Apple Technical Note TN2187 for details on IOHidManager. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "hidapi.h"
+
+/* Barrier implementation because Mac OSX doesn't have pthread_barrier.
+ It also doesn't have clock_gettime(). So much for POSIX and SUSv2.
+ This implementation came from Brent Priddy and was posted on
+ StackOverflow. It is used with his permission. */
+typedef int pthread_barrierattr_t;
+typedef struct pthread_barrier {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int count;
+ int trip_count;
+} pthread_barrier_t;
+
+static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
+{
+ if(count == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
+ return -1;
+ }
+ if(pthread_cond_init(&barrier->cond, 0) < 0) {
+ pthread_mutex_destroy(&barrier->mutex);
+ return -1;
+ }
+ barrier->trip_count = count;
+ barrier->count = 0;
+
+ return 0;
+}
+
+static int pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+ pthread_cond_destroy(&barrier->cond);
+ pthread_mutex_destroy(&barrier->mutex);
+ return 0;
+}
+
+static int pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+ pthread_mutex_lock(&barrier->mutex);
+ ++(barrier->count);
+ if(barrier->count >= barrier->trip_count)
+ {
+ barrier->count = 0;
+ pthread_cond_broadcast(&barrier->cond);
+ pthread_mutex_unlock(&barrier->mutex);
+ return 1;
+ }
+ else
+ {
+ pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+ pthread_mutex_unlock(&barrier->mutex);
+ return 0;
+ }
+}
+
+static int return_data(hid_device *dev, unsigned char *data, size_t length);
+
+/* Linked List of input reports received from the device. */
+struct input_report {
+ uint8_t *data;
+ size_t len;
+ struct input_report *next;
+};
+
+struct hid_device_ {
+ IOHIDDeviceRef device_handle;
+ int blocking;
+ int uses_numbered_reports;
+ int disconnected;
+ CFStringRef run_loop_mode;
+ CFRunLoopRef run_loop;
+ CFRunLoopSourceRef source;
+ uint8_t *input_report_buf;
+ CFIndex max_input_report_len;
+ struct input_report *input_reports;
+
+ pthread_t thread;
+ pthread_mutex_t mutex; /* Protects input_reports */
+ pthread_cond_t condition;
+ pthread_barrier_t barrier; /* Ensures correct startup sequence */
+ pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */
+ int shutdown_thread;
+};
+
+static hid_device *new_hid_device(void)
+{
+ hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
+ dev->device_handle = NULL;
+ dev->blocking = 1;
+ dev->uses_numbered_reports = 0;
+ dev->disconnected = 0;
+ dev->run_loop_mode = NULL;
+ dev->run_loop = NULL;
+ dev->source = NULL;
+ dev->input_report_buf = NULL;
+ dev->input_reports = NULL;
+ dev->shutdown_thread = 0;
+
+ /* Thread objects */
+ pthread_mutex_init(&dev->mutex, NULL);
+ pthread_cond_init(&dev->condition, NULL);
+ pthread_barrier_init(&dev->barrier, NULL, 2);
+ pthread_barrier_init(&dev->shutdown_barrier, NULL, 2);
+
+ return dev;
+}
+
+static void free_hid_device(hid_device *dev)
+{
+ if (!dev)
+ return;
+
+ /* Delete any input reports still left over. */
+ struct input_report *rpt = dev->input_reports;
+ while (rpt) {
+ struct input_report *next = rpt->next;
+ free(rpt->data);
+ free(rpt);
+ rpt = next;
+ }
+
+ /* Free the string and the report buffer. The check for NULL
+ is necessary here as CFRelease() doesn't handle NULL like
+ free() and others do. */
+ if (dev->run_loop_mode)
+ CFRelease(dev->run_loop_mode);
+ if (dev->source)
+ CFRelease(dev->source);
+ free(dev->input_report_buf);
+
+ /* Clean up the thread objects */
+ pthread_barrier_destroy(&dev->shutdown_barrier);
+ pthread_barrier_destroy(&dev->barrier);
+ pthread_cond_destroy(&dev->condition);
+ pthread_mutex_destroy(&dev->mutex);
+
+ /* Free the structure itself. */
+ free(dev);
+}
+
+static IOHIDManagerRef hid_mgr = 0x0;
+
+
+#if 0
+static void register_error(hid_device *dev, const char *op)
+{
+
+}
+#endif
+
+static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key)
+{
+ CFTypeRef ref = IOHIDDeviceGetProperty(device, key);
+ if (ref != NULL && CFGetTypeID(ref) == CFArrayGetTypeID()) {
+ return (CFArrayRef)ref;
+ } else {
+ return NULL;
+ }
+}
+
+static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
+{
+ CFTypeRef ref;
+ int32_t value;
+
+ ref = IOHIDDeviceGetProperty(device, key);
+ if (ref) {
+ if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
+ CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value);
+ return value;
+ }
+ }
+ return 0;
+}
+
+static CFArrayRef get_usage_pairs(IOHIDDeviceRef device)
+{
+ return get_array_property(device, CFSTR(kIOHIDDeviceUsagePairsKey));
+}
+
+static unsigned short get_vendor_id(IOHIDDeviceRef device)
+{
+ return get_int_property(device, CFSTR(kIOHIDVendorIDKey));
+}
+
+static unsigned short get_product_id(IOHIDDeviceRef device)
+{
+ return get_int_property(device, CFSTR(kIOHIDProductIDKey));
+}
+
+static int32_t get_max_report_length(IOHIDDeviceRef device)
+{
+ return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey));
+}
+
+static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
+{
+ CFStringRef str;
+
+ if (!len)
+ return 0;
+
+ str = (CFStringRef) IOHIDDeviceGetProperty(device, prop);
+
+ buf[0] = 0;
+
+ if (str) {
+ CFIndex str_len = CFStringGetLength(str);
+ CFRange range;
+ CFIndex used_buf_len;
+ CFIndex chars_copied;
+
+ len --;
+
+ range.location = 0;
+ range.length = ((size_t) str_len > len)? len: (size_t) str_len;
+ chars_copied = CFStringGetBytes(str,
+ range,
+ kCFStringEncodingUTF32LE,
+ (char) '?',
+ FALSE,
+ (UInt8*)buf,
+ len * sizeof(wchar_t),
+ &used_buf_len);
+
+ if (chars_copied == len)
+ buf[len] = 0; /* len is decremented above */
+ else
+ buf[chars_copied] = 0;
+
+ return 0;
+ }
+ else
+ return -1;
+
+}
+
+static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+ return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
+}
+
+static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+ return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len);
+}
+
+static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+ return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len);
+}
+
+
+/* Implementation of wcsdup() for Mac. */
+static wchar_t *dup_wcs(const wchar_t *s)
+{
+ size_t len = wcslen(s);
+ wchar_t *ret = (wchar_t*) malloc((len+1)*sizeof(wchar_t));
+ wcscpy(ret, s);
+
+ return ret;
+}
+
+/* hidapi_IOHIDDeviceGetService()
+ *
+ * Return the io_service_t corresponding to a given IOHIDDeviceRef, either by:
+ * - on OS X 10.6 and above, calling IOHIDDeviceGetService()
+ * - on OS X 10.5, extract it from the IOHIDDevice struct
+ */
+static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device)
+{
+ static void *iokit_framework = NULL;
+ typedef io_service_t (*dynamic_IOHIDDeviceGetService_t)(IOHIDDeviceRef device);
+ static dynamic_IOHIDDeviceGetService_t dynamic_IOHIDDeviceGetService = NULL;
+
+ /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists.
+ * If any of these steps fail, dynamic_IOHIDDeviceGetService will be left NULL
+ * and the fallback method will be used.
+ */
+ if (iokit_framework == NULL) {
+ iokit_framework = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_LAZY);
+
+ if (iokit_framework != NULL)
+ dynamic_IOHIDDeviceGetService = (dynamic_IOHIDDeviceGetService_t) dlsym(iokit_framework, "IOHIDDeviceGetService");
+ }
+
+ if (dynamic_IOHIDDeviceGetService != NULL) {
+ /* Running on OS X 10.6 and above: IOHIDDeviceGetService() exists */
+ return dynamic_IOHIDDeviceGetService(device);
+ }
+ else
+ {
+ /* Running on OS X 10.5: IOHIDDeviceGetService() doesn't exist.
+ *
+ * Be naughty and pull the service out of the IOHIDDevice.
+ * IOHIDDevice is an opaque struct not exposed to applications, but its
+ * layout is stable through all available versions of OS X.
+ * Tested and working on OS X 10.5.8 i386, x86_64, and ppc.
+ */
+ struct IOHIDDevice_internal {
+ /* The first field of the IOHIDDevice struct is a
+ * CFRuntimeBase (which is a private CF struct).
+ *
+ * a, b, and c are the 3 fields that make up a CFRuntimeBase.
+ * See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h
+ *
+ * The second field of the IOHIDDevice is the io_service_t we're looking for.
+ */
+ uintptr_t a;
+ uint8_t b[4];
+#if __LP64__
+ uint32_t c;
+#endif
+ io_service_t service;
+ };
+ struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *) device;
+
+ return tmp->service;
+ }
+}
+
+/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
+static int init_hid_manager(void)
+{
+ /* Initialize all the HID Manager Objects */
+ hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (hid_mgr) {
+ IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
+ IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Initialize the IOHIDManager if necessary. This is the public function, and
+ it is safe to call this function repeatedly. Return 0 for success and -1
+ for failure. */
+int HID_API_EXPORT hid_init(void)
+{
+ if (!hid_mgr) {
+ return init_hid_manager();
+ }
+
+ /* Already initialized. */
+ return 0;
+}
+
+int HID_API_EXPORT hid_exit(void)
+{
+ if (hid_mgr) {
+ /* Close the HID manager. */
+ IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone);
+ CFRelease(hid_mgr);
+ hid_mgr = NULL;
+ }
+
+ return 0;
+}
+
+static void process_pending_events(void) {
+ SInt32 res;
+ do {
+ res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
+ } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut);
+}
+
+static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, int32_t usage_page, int32_t usage)
+{
+ unsigned short dev_vid;
+ unsigned short dev_pid;
+ int BUF_LEN = 256;
+ wchar_t buf[BUF_LEN];
+
+ struct hid_device_info *cur_dev;
+ io_object_t iokit_dev;
+ kern_return_t res;
+ io_string_t path;
+
+ if (dev == NULL) {
+ return NULL;
+ }
+
+ cur_dev = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info));
+ if (cur_dev == NULL) {
+ return NULL;
+ }
+
+ dev_vid = get_vendor_id(dev);
+ dev_pid = get_product_id(dev);
+
+ cur_dev->usage_page = usage_page;
+ cur_dev->usage = usage;
+
+ /* Fill out the record */
+ cur_dev->next = NULL;
+
+ /* Fill in the path (IOService plane) */
+ iokit_dev = hidapi_IOHIDDeviceGetService(dev);
+ res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
+ if (res == KERN_SUCCESS)
+ cur_dev->path = strdup(path);
+ else
+ cur_dev->path = strdup("");
+
+ /* Serial Number */
+ get_serial_number(dev, buf, BUF_LEN);
+ cur_dev->serial_number = dup_wcs(buf);
+
+ /* Manufacturer and Product strings */
+ get_manufacturer_string(dev, buf, BUF_LEN);
+ cur_dev->manufacturer_string = dup_wcs(buf);
+ get_product_string(dev, buf, BUF_LEN);
+ cur_dev->product_string = dup_wcs(buf);
+
+ /* VID/PID */
+ cur_dev->vendor_id = dev_vid;
+ cur_dev->product_id = dev_pid;
+
+ /* Release Number */
+ cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
+
+ /* Interface Number */
+ /* We can only retrieve the interface number for USB HID devices.
+ * IOKit always seems to return 0 when querying a standard USB device
+ * for its interface. */
+ bool is_usb_hid = get_int_property(dev, CFSTR(kUSBInterfaceClass)) == kUSBHIDClass;
+ if (is_usb_hid) {
+ /* Get the interface number */
+ cur_dev->interface_number = get_int_property(dev, CFSTR(kUSBInterfaceNumber));
+ } else {
+ cur_dev->interface_number = -1;
+ }
+
+ return cur_dev;
+}
+
+static struct hid_device_info *create_device_info(IOHIDDeviceRef device)
+{
+ struct hid_device_info *root = NULL;
+ CFArrayRef usage_pairs = get_usage_pairs(device);
+
+ if (usage_pairs != NULL) {
+ struct hid_device_info *cur = NULL;
+ struct hid_device_info *next = NULL;
+ for (CFIndex i = 0; i < CFArrayGetCount(usage_pairs); i++) {
+ CFTypeRef dict = CFArrayGetValueAtIndex(usage_pairs, i);
+ if (CFGetTypeID(dict) != CFDictionaryGetTypeID()) {
+ continue;
+ }
+
+ CFTypeRef usage_page_ref, usage_ref;
+ int32_t usage_page, usage;
+
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)dict, CFSTR(kIOHIDDeviceUsagePageKey), &usage_page_ref) ||
+ !CFDictionaryGetValueIfPresent((CFDictionaryRef)dict, CFSTR(kIOHIDDeviceUsageKey), &usage_ref) ||
+ CFGetTypeID(usage_page_ref) != CFNumberGetTypeID() ||
+ CFGetTypeID(usage_ref) != CFNumberGetTypeID() ||
+ !CFNumberGetValue((CFNumberRef)usage_page_ref, kCFNumberSInt32Type, &usage_page) ||
+ !CFNumberGetValue((CFNumberRef)usage_ref, kCFNumberSInt32Type, &usage)) {
+ continue;
+ }
+ next = create_device_info_with_usage(device, usage_page, usage);
+ if (cur == NULL) {
+ root = next;
+ }
+ else {
+ cur->next = next;
+ }
+ if (next != NULL) {
+ cur = next;
+ }
+ }
+ }
+
+ if (root == NULL) {
+ /* error when generating or parsing usage pairs */
+ int32_t usage_page = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
+ int32_t usage = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
+
+ root = create_device_info_with_usage(device, usage_page, usage);
+ }
+
+ return root;
+}
+
+struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ struct hid_device_info *root = NULL; /* return object */
+ struct hid_device_info *cur_dev = NULL;
+ CFIndex num_devices;
+ int i;
+
+ /* Set up the HID Manager if it hasn't been done */
+ if (hid_init() < 0)
+ return NULL;
+
+ /* give the IOHIDManager a chance to update itself */
+ process_pending_events();
+
+ /* Get a list of the Devices */
+ CFMutableDictionaryRef matching = NULL;
+ if (vendor_id != 0 || product_id != 0) {
+ matching = CFDictionaryCreateMutable(kCFAllocatorDefault, kIOHIDOptionsTypeNone, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ if (matching && vendor_id != 0) {
+ CFNumberRef v = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &vendor_id);
+ CFDictionarySetValue(matching, CFSTR(kIOHIDVendorIDKey), v);
+ CFRelease(v);
+ }
+
+ if (matching && product_id != 0) {
+ CFNumberRef p = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &product_id);
+ CFDictionarySetValue(matching, CFSTR(kIOHIDProductIDKey), p);
+ CFRelease(p);
+ }
+ }
+ IOHIDManagerSetDeviceMatching(hid_mgr, matching);
+ if (matching != NULL) {
+ CFRelease(matching);
+ }
+
+ CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
+
+ /* Convert the list into a C array so we can iterate easily. */
+ num_devices = CFSetGetCount(device_set);
+ IOHIDDeviceRef *device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef));
+ CFSetGetValues(device_set, (const void **) device_array);
+
+ /* Iterate over each device, making an entry for it. */
+ for (i = 0; i < num_devices; i++) {
+
+ IOHIDDeviceRef dev = device_array[i];
+ if (!dev) {
+ continue;
+ }
+
+ struct hid_device_info *tmp = create_device_info(dev);
+ if (tmp == NULL) {
+ continue;
+ }
+
+ if (cur_dev) {
+ cur_dev->next = tmp;
+ }
+ else {
+ root = tmp;
+ }
+ cur_dev = tmp;
+
+ /* move the pointer to the tail of returnd list */
+ while (cur_dev->next != NULL) {
+ cur_dev = cur_dev->next;
+ }
+ }
+
+ free(device_array);
+ CFRelease(device_set);
+
+ return root;
+}
+
+void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
+{
+ /* This function is identical to the Linux version. Platform independent. */
+ struct hid_device_info *d = devs;
+ while (d) {
+ struct hid_device_info *next = d->next;
+ free(d->path);
+ free(d->serial_number);
+ free(d->manufacturer_string);
+ free(d->product_string);
+ free(d);
+ d = next;
+ }
+}
+
+hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+ /* This function is identical to the Linux version. Platform independent. */
+ struct hid_device_info *devs, *cur_dev;
+ const char *path_to_open = NULL;
+ hid_device * handle = NULL;
+
+ devs = hid_enumerate(vendor_id, product_id);
+ cur_dev = devs;
+ while (cur_dev) {
+ if (cur_dev->vendor_id == vendor_id &&
+ cur_dev->product_id == product_id) {
+ if (serial_number) {
+ if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ else {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ cur_dev = cur_dev->next;
+ }
+
+ if (path_to_open) {
+ /* Open the device */
+ handle = hid_open_path(path_to_open);
+ }
+
+ hid_free_enumeration(devs);
+
+ return handle;
+}
+
+static void hid_device_removal_callback(void *context, IOReturn result,
+ void *sender)
+{
+ /* Stop the Run Loop for this device. */
+ hid_device *d = (hid_device*) context;
+
+ d->disconnected = 1;
+ CFRunLoopStop(d->run_loop);
+}
+
+/* The Run Loop calls this function for each input report received.
+ This function puts the data into a linked list to be picked up by
+ hid_read(). */
+static void hid_report_callback(void *context, IOReturn result, void *sender,
+ IOHIDReportType report_type, uint32_t report_id,
+ uint8_t *report, CFIndex report_length)
+{
+ struct input_report *rpt;
+ hid_device *dev = (hid_device*) context;
+
+ /* Make a new Input Report object */
+ rpt = (struct input_report*) calloc(1, sizeof(struct input_report));
+ rpt->data = (uint8_t*) calloc(1, report_length);
+ memcpy(rpt->data, report, report_length);
+ rpt->len = report_length;
+ rpt->next = NULL;
+
+ /* Lock this section */
+ pthread_mutex_lock(&dev->mutex);
+
+ /* Attach the new report object to the end of the list. */
+ if (dev->input_reports == NULL) {
+ /* The list is empty. Put it at the root. */
+ dev->input_reports = rpt;
+ }
+ else {
+ /* Find the end of the list and attach. */
+ struct input_report *cur = dev->input_reports;
+ int num_queued = 0;
+ while (cur->next != NULL) {
+ cur = cur->next;
+ num_queued++;
+ }
+ cur->next = rpt;
+
+ /* Pop one off if we've reached 30 in the queue. This
+ way we don't grow forever if the user never reads
+ anything from the device. */
+ if (num_queued > 30) {
+ return_data(dev, NULL, 0);
+ }
+ }
+
+ /* Signal a waiting thread that there is data. */
+ pthread_cond_signal(&dev->condition);
+
+ /* Unlock */
+ pthread_mutex_unlock(&dev->mutex);
+
+}
+
+/* This gets called when the read_thread's run loop gets signaled by
+ hid_close(), and serves to stop the read_thread's run loop. */
+static void perform_signal_callback(void *context)
+{
+ hid_device *dev = (hid_device*) context;
+ CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/
+}
+
+static void *read_thread(void *param)
+{
+ hid_device *dev = (hid_device*) param;
+ SInt32 code;
+
+ /* Move the device's run loop to this thread. */
+ IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
+
+ /* Create the RunLoopSource which is used to signal the
+ event loop to stop when hid_close() is called. */
+ CFRunLoopSourceContext ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.version = 0;
+ ctx.info = dev;
+ ctx.perform = &perform_signal_callback;
+ dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);
+
+ /* Store off the Run Loop so it can be stopped from hid_close()
+ and on device disconnection. */
+ dev->run_loop = CFRunLoopGetCurrent();
+
+ /* Notify the main thread that the read thread is up and running. */
+ pthread_barrier_wait(&dev->barrier);
+
+ /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
+ reports into the hid_report_callback(). */
+ while (!dev->shutdown_thread && !dev->disconnected) {
+ code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
+ /* Return if the device has been disconnected */
+ if (code == kCFRunLoopRunFinished) {
+ dev->disconnected = 1;
+ break;
+ }
+
+
+ /* Break if The Run Loop returns Finished or Stopped. */
+ if (code != kCFRunLoopRunTimedOut &&
+ code != kCFRunLoopRunHandledSource) {
+ /* There was some kind of error. Setting
+ shutdown seems to make sense, but
+ there may be something else more appropriate */
+ dev->shutdown_thread = 1;
+ break;
+ }
+ }
+
+ /* Now that the read thread is stopping, Wake any threads which are
+ waiting on data (in hid_read_timeout()). Do this under a mutex to
+ make sure that a thread which is about to go to sleep waiting on
+ the condition actually will go to sleep before the condition is
+ signaled. */
+ pthread_mutex_lock(&dev->mutex);
+ pthread_cond_broadcast(&dev->condition);
+ pthread_mutex_unlock(&dev->mutex);
+
+ /* Wait here until hid_close() is called and makes it past
+ the call to CFRunLoopWakeUp(). This thread still needs to
+ be valid when that function is called on the other thread. */
+ pthread_barrier_wait(&dev->shutdown_barrier);
+
+ return NULL;
+}
+
+/* hid_open_path()
+ *
+ * path must be a valid path to an IOHIDDevice in the IOService plane
+ * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver"
+ */
+hid_device * HID_API_EXPORT hid_open_path(const char *path)
+{
+ hid_device *dev = NULL;
+ io_registry_entry_t entry = MACH_PORT_NULL;
+ IOReturn ret = kIOReturnInvalid;
+
+ /* Set up the HID Manager if it hasn't been done */
+ if (hid_init() < 0)
+ goto return_error;
+
+ dev = new_hid_device();
+
+ /* Get the IORegistry entry for the given path */
+ entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);
+ if (entry == MACH_PORT_NULL) {
+ /* Path wasn't valid (maybe device was removed?) */
+ goto return_error;
+ }
+
+ /* Create an IOHIDDevice for the entry */
+ dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
+ if (dev->device_handle == NULL) {
+ /* Error creating the HID device */
+ goto return_error;
+ }
+
+ /* Open the IOHIDDevice */
+ ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
+ if (ret == kIOReturnSuccess) {
+ char str[32];
+
+ /* Create the buffers for receiving data */
+ dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle);
+ dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t));
+
+ /* Create the Run Loop Mode for this device.
+ printing the reference seems to work. */
+ sprintf(str, "HIDAPI_%p", dev->device_handle);
+ dev->run_loop_mode =
+ CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
+
+ /* Attach the device to a Run Loop */
+ IOHIDDeviceRegisterInputReportCallback(
+ dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
+ &hid_report_callback, dev);
+ IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
+
+ /* Start the read thread */
+ pthread_create(&dev->thread, NULL, read_thread, dev);
+
+ /* Wait here for the read thread to be initialized. */
+ pthread_barrier_wait(&dev->barrier);
+
+ IOObjectRelease(entry);
+ return dev;
+ }
+ else {
+ goto return_error;
+ }
+
+return_error:
+ if (dev->device_handle != NULL)
+ CFRelease(dev->device_handle);
+
+ if (entry != MACH_PORT_NULL)
+ IOObjectRelease(entry);
+
+ free_hid_device(dev);
+ return NULL;
+}
+
+static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length)
+{
+ const unsigned char *data_to_send = data;
+ CFIndex length_to_send = length;
+ IOReturn res;
+ const unsigned char report_id = data[0];
+
+ if (report_id == 0x0) {
+ /* Not using numbered Reports.
+ Don't send the report number. */
+ data_to_send = data+1;
+ length_to_send = length-1;
+ }
+
+ /* Avoid crash if the device has been unplugged. */
+ if (dev->disconnected) {
+ return -1;
+ }
+
+ res = IOHIDDeviceSetReport(dev->device_handle,
+ type,
+ report_id,
+ data_to_send, length_to_send);
+
+ if (res == kIOReturnSuccess) {
+ return length;
+ }
+
+ return -1;
+}
+
+static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length)
+{
+ unsigned char *report = data;
+ CFIndex report_length = length;
+ IOReturn res = kIOReturnSuccess;
+ const unsigned char report_id = data[0];
+
+ if (report_id == 0x0) {
+ /* Not using numbered Reports.
+ Don't send the report number. */
+ report = data+1;
+ report_length = length-1;
+ }
+
+ /* Avoid crash if the device has been unplugged. */
+ if (dev->disconnected) {
+ return -1;
+ }
+
+ res = IOHIDDeviceGetReport(dev->device_handle,
+ type,
+ report_id,
+ report, &report_length);
+
+ if (res == kIOReturnSuccess) {
+ if (report_id == 0x0) { // 0 report number still present at the beginning
+ report_length++;
+ }
+ return report_length;
+ }
+
+ return -1;
+}
+
+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+ return set_report(dev, kIOHIDReportTypeOutput, data, length);
+}
+
+/* Helper function, so that this isn't duplicated in hid_read(). */
+static int return_data(hid_device *dev, unsigned char *data, size_t length)
+{
+ /* Copy the data out of the linked list item (rpt) into the
+ return buffer (data), and delete the liked list item. */
+ struct input_report *rpt = dev->input_reports;
+ size_t len = (length < rpt->len)? length: rpt->len;
+ memcpy(data, rpt->data, len);
+ dev->input_reports = rpt->next;
+ free(rpt->data);
+ free(rpt);
+ return len;
+}
+
+static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+ while (!dev->input_reports) {
+ int res = pthread_cond_wait(cond, mutex);
+ if (res != 0)
+ return res;
+
+ /* A res of 0 means we may have been signaled or it may
+ be a spurious wakeup. Check to see that there's actually
+ data in the queue before returning, and if not, go back
+ to sleep. See the pthread_cond_timedwait() man page for
+ details. */
+
+ if (dev->shutdown_thread || dev->disconnected)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
+{
+ while (!dev->input_reports) {
+ int res = pthread_cond_timedwait(cond, mutex, abstime);
+ if (res != 0)
+ return res;
+
+ /* A res of 0 means we may have been signaled or it may
+ be a spurious wakeup. Check to see that there's actually
+ data in the queue before returning, and if not, go back
+ to sleep. See the pthread_cond_timedwait() man page for
+ details. */
+
+ if (dev->shutdown_thread || dev->disconnected)
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+ int bytes_read = -1;
+
+ /* Lock the access to the report list. */
+ pthread_mutex_lock(&dev->mutex);
+
+ /* There's an input report queued up. Return it. */
+ if (dev->input_reports) {
+ /* Return the first one */
+ bytes_read = return_data(dev, data, length);
+ goto ret;
+ }
+
+ /* Return if the device has been disconnected. */
+ if (dev->disconnected) {
+ bytes_read = -1;
+ goto ret;
+ }
+
+ if (dev->shutdown_thread) {
+ /* This means the device has been closed (or there
+ has been an error. An error code of -1 should
+ be returned. */
+ bytes_read = -1;
+ goto ret;
+ }
+
+ /* There is no data. Go to sleep and wait for data. */
+
+ if (milliseconds == -1) {
+ /* Blocking */
+ int res;
+ res = cond_wait(dev, &dev->condition, &dev->mutex);
+ if (res == 0)
+ bytes_read = return_data(dev, data, length);
+ else {
+ /* There was an error, or a device disconnection. */
+ bytes_read = -1;
+ }
+ }
+ else if (milliseconds > 0) {
+ /* Non-blocking, but called with timeout. */
+ int res;
+ struct timespec ts;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ ts.tv_sec += milliseconds / 1000;
+ ts.tv_nsec += (milliseconds % 1000) * 1000000;
+ if (ts.tv_nsec >= 1000000000L) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
+ }
+
+ res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts);
+ if (res == 0)
+ bytes_read = return_data(dev, data, length);
+ else if (res == ETIMEDOUT)
+ bytes_read = 0;
+ else
+ bytes_read = -1;
+ }
+ else {
+ /* Purely non-blocking */
+ bytes_read = 0;
+ }
+
+ret:
+ /* Unlock */
+ pthread_mutex_unlock(&dev->mutex);
+ return bytes_read;
+}
+
+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+ return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
+}
+
+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+ /* All Nonblocking operation is handled by the library. */
+ dev->blocking = !nonblock;
+
+ return 0;
+}
+
+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+ return set_report(dev, kIOHIDReportTypeFeature, data, length);
+}
+
+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ return get_report(dev, kIOHIDReportTypeFeature, data, length);
+}
+
+int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ return get_report(dev, kIOHIDReportTypeInput, data, length);
+}
+
+void HID_API_EXPORT hid_close(hid_device *dev)
+{
+ if (!dev)
+ return;
+
+ /* Disconnect the report callback before close. */
+ if (!dev->disconnected) {
+ IOHIDDeviceRegisterInputReportCallback(
+ dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
+ NULL, dev);
+ IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
+ IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
+ IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+ }
+
+ /* Cause read_thread() to stop. */
+ dev->shutdown_thread = 1;
+
+ /* Wake up the run thread's event loop so that the thread can exit. */
+ CFRunLoopSourceSignal(dev->source);
+ CFRunLoopWakeUp(dev->run_loop);
+
+ /* Notify the read thread that it can shut down now. */
+ pthread_barrier_wait(&dev->shutdown_barrier);
+
+ /* Wait for read_thread() to end. */
+ pthread_join(dev->thread, NULL);
+
+ /* Close the OS handle to the device, but only if it's not
+ been unplugged. If it's been unplugged, then calling
+ IOHIDDeviceClose() will crash. */
+ if (!dev->disconnected) {
+ IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
+ }
+
+ /* Clear out the queue of received reports. */
+ pthread_mutex_lock(&dev->mutex);
+ while (dev->input_reports) {
+ return_data(dev, NULL, 0);
+ }
+ pthread_mutex_unlock(&dev->mutex);
+ CFRelease(dev->device_handle);
+
+ free_hid_device(dev);
+}
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_manufacturer_string(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_product_string(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return get_serial_number(dev->device_handle, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+ /* TODO: */
+
+ return 0;
+}
+
+
+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
+{
+ /* TODO: */
+
+ return L"hid_error is not implemented yet";
+}
+
+
+
+
+
+
+
+#if 0
+static int32_t get_location_id(IOHIDDeviceRef device)
+{
+ return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
+}
+
+static int32_t get_usage(IOHIDDeviceRef device)
+{
+ int32_t res;
+ res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey));
+ if (!res)
+ res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
+ return res;
+}
+
+static int32_t get_usage_page(IOHIDDeviceRef device)
+{
+ int32_t res;
+ res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey));
+ if (!res)
+ res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
+ return res;
+}
+
+static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len)
+{
+ return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len);
+}
+
+
+int main(void)
+{
+ IOHIDManagerRef mgr;
+ int i;
+
+ mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ IOHIDManagerSetDeviceMatching(mgr, NULL);
+ IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);
+
+ CFSetRef device_set = IOHIDManagerCopyDevices(mgr);
+
+ CFIndex num_devices = CFSetGetCount(device_set);
+ IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
+ CFSetGetValues(device_set, (const void **) device_array);
+
+ for (i = 0; i < num_devices; i++) {
+ IOHIDDeviceRef dev = device_array[i];
+ printf("Device: %p\n", dev);
+ printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev));
+
+ wchar_t serial[256], buf[256];
+ char cbuf[256];
+ get_serial_number(dev, serial, 256);
+
+
+ printf(" Serial: %ls\n", serial);
+ printf(" Loc: %ld\n", get_location_id(dev));
+ get_transport(dev, buf, 256);
+ printf(" Trans: %ls\n", buf);
+ make_path(dev, cbuf, 256);
+ printf(" Path: %s\n", cbuf);
+
+ }
+
+ return 0;
+}
+#endif
diff --git a/c/src/third-party/hidapi/pc/.gitignore b/c/src/third-party/hidapi/pc/.gitignore
new file mode 100644
index 000000000..6fd0ef029
--- /dev/null
+++ b/c/src/third-party/hidapi/pc/.gitignore
@@ -0,0 +1 @@
+*.pc
diff --git a/c/src/third-party/hidapi/pc/hidapi-hidraw.pc.in b/c/src/third-party/hidapi/pc/hidapi-hidraw.pc.in
new file mode 100644
index 000000000..e20558d5a
--- /dev/null
+++ b/c/src/third-party/hidapi/pc/hidapi-hidraw.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: hidapi-hidraw
+Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the hidraw implementation.
+Version: @VERSION@
+Libs: -L${libdir} -lhidapi-hidraw
+Cflags: -I${includedir}/hidapi
diff --git a/c/src/third-party/hidapi/pc/hidapi-libusb.pc.in b/c/src/third-party/hidapi/pc/hidapi-libusb.pc.in
new file mode 100644
index 000000000..2e4950655
--- /dev/null
+++ b/c/src/third-party/hidapi/pc/hidapi-libusb.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: hidapi-libusb
+Description: C Library for USB HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the libusb implementation.
+Version: @VERSION@
+Libs: -L${libdir} -lhidapi-libusb
+Cflags: -I${includedir}/hidapi
diff --git a/c/src/third-party/hidapi/pc/hidapi.pc.in b/c/src/third-party/hidapi/pc/hidapi.pc.in
new file mode 100644
index 000000000..5835c99bf
--- /dev/null
+++ b/c/src/third-party/hidapi/pc/hidapi.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: hidapi
+Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows.
+Version: @VERSION@
+Libs: -L${libdir} -lhidapi
+Cflags: -I${includedir}/hidapi
diff --git a/c/src/third-party/hidapi/testgui/.gitignore b/c/src/third-party/hidapi/testgui/.gitignore
new file mode 100644
index 000000000..f989ea8c2
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/.gitignore
@@ -0,0 +1,20 @@
+Debug
+Release
+*.exp
+*.ilk
+*.lib
+*.suo
+*.vcproj.*
+*.ncb
+*.suo
+*.dll
+*.pdb
+*.o
+hidapi-testgui
+hidapi-hidraw-testgui
+hidapi-libusb-testgui
+.deps
+.libs
+*.la
+*.lo
+TestGUI.app
diff --git a/c/src/third-party/hidapi/testgui/Makefile-manual b/c/src/third-party/hidapi/testgui/Makefile-manual
new file mode 100644
index 000000000..3f61705f2
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile-manual
@@ -0,0 +1,26 @@
+
+
+OS=$(shell uname)
+
+ifeq ($(OS), Darwin)
+ FILE=Makefile.mac
+endif
+
+ifneq (,$(findstring MINGW,$(OS)))
+ FILE=Makefile.mingw
+endif
+
+ifeq ($(OS), Linux)
+ FILE=Makefile.linux
+endif
+
+ifeq ($(OS), FreeBSD)
+ FILE=Makefile.freebsd
+endif
+
+ifeq ($(FILE), )
+all:
+ $(error Your platform ${OS} is not supported at this time.)
+endif
+
+include $(FILE)
diff --git a/c/src/third-party/hidapi/testgui/Makefile.am b/c/src/third-party/hidapi/testgui/Makefile.am
new file mode 100644
index 000000000..1c02f3f2c
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile.am
@@ -0,0 +1,43 @@
+
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_TESTGUI)
+
+if OS_LINUX
+## Linux
+bin_PROGRAMS = hidapi-hidraw-testgui hidapi-libusb-testgui
+
+hidapi_hidraw_testgui_SOURCES = test.cpp
+hidapi_hidraw_testgui_LDADD = $(top_builddir)/linux/libhidapi-hidraw.la $(LIBS_TESTGUI)
+
+hidapi_libusb_testgui_SOURCES = test.cpp
+hidapi_libusb_testgui_LDADD = $(top_builddir)/libusb/libhidapi-libusb.la $(LIBS_TESTGUI)
+else
+## Other OS's
+bin_PROGRAMS = hidapi-testgui
+
+hidapi_testgui_SOURCES = test.cpp
+hidapi_testgui_LDADD = $(top_builddir)/$(backend)/libhidapi.la $(LIBS_TESTGUI)
+endif
+
+if OS_DARWIN
+hidapi_testgui_SOURCES = test.cpp mac_support_cocoa.m mac_support.h
+# Rules for copying the binary and its dependencies into the app bundle.
+TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT): hidapi-testgui$(EXEEXT)
+ $(srcdir)/copy_to_bundle.sh
+
+all: all-am TestGUI.app/Contents/MacOS/hidapi-testgui$(EXEEXT)
+
+endif
+
+EXTRA_DIST = \
+ copy_to_bundle.sh \
+ Makefile-manual \
+ Makefile.freebsd \
+ Makefile.linux \
+ Makefile.mac \
+ Makefile.mingw \
+ TestGUI.app.in \
+ testgui.sln \
+ testgui.vcproj
+
+distclean-local:
+ rm -rf TestGUI.app
diff --git a/c/src/third-party/hidapi/testgui/Makefile.freebsd b/c/src/third-party/hidapi/testgui/Makefile.freebsd
new file mode 100644
index 000000000..09a24737c
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile.freebsd
@@ -0,0 +1,33 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: testgui
+
+CC=cc
+CXX=c++
+COBJS=../libusb/hid.o
+CPPOBJS=test.o
+OBJS=$(COBJS) $(CPPOBJS)
+CFLAGS=-I../hidapi -I/usr/local/include `fox-config --cflags` -Wall -g -c
+LDFLAGS= -L/usr/local/lib
+LIBS= -lusb -liconv `fox-config --libs` -pthread
+
+
+testgui: $(OBJS)
+ $(CXX) -Wall -g $^ $(LDFLAGS) -o $@ $(LIBS)
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+$(CPPOBJS): %.o: %.cpp
+ $(CXX) $(CFLAGS) $< -o $@
+
+clean:
+ rm *.o testgui
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/testgui/Makefile.linux b/c/src/third-party/hidapi/testgui/Makefile.linux
new file mode 100644
index 000000000..d32e16317
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile.linux
@@ -0,0 +1,32 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: testgui
+
+CC=gcc
+CXX=g++
+COBJS=../libusb/hid.o
+CPPOBJS=test.o
+OBJS=$(COBJS) $(CPPOBJS)
+CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags` `pkg-config libusb-1.0 --cflags`
+LIBS=-ludev -lrt -lpthread `fox-config --libs` `pkg-config libusb-1.0 --libs`
+
+
+testgui: $(OBJS)
+ g++ -Wall -g $^ $(LIBS) -o testgui
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+$(CPPOBJS): %.o: %.cpp
+ $(CXX) $(CFLAGS) $< -o $@
+
+clean:
+ rm *.o testgui
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/testgui/Makefile.mac b/c/src/third-party/hidapi/testgui/Makefile.mac
new file mode 100644
index 000000000..cda7d49e9
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile.mac
@@ -0,0 +1,46 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-07-03
+###########################################
+
+all: hidapi-testgui
+
+CC=gcc
+CXX=g++
+COBJS=../mac/hid.o
+CPPOBJS=test.o
+OBJCOBJS=mac_support_cocoa.o
+OBJS=$(COBJS) $(CPPOBJS) $(OBJCOBJS)
+CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags`
+LDFLAGS=-L/usr/X11R6/lib
+LIBS=`fox-config --libs` -framework IOKit -framework CoreFoundation -framework Cocoa
+
+
+hidapi-testgui: $(OBJS) TestGUI.app
+ g++ -Wall -g $(OBJS) $(LIBS) $(LDFLAGS) -o hidapi-testgui
+ ./copy_to_bundle.sh
+ #cp TestGUI.app/Contents/MacOS/hidapi-testgui TestGUI.app/Contents/MacOS/tg
+ #cp start.sh TestGUI.app/Contents/MacOS/hidapi-testgui
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+$(CPPOBJS): %.o: %.cpp
+ $(CXX) $(CFLAGS) $< -o $@
+
+$(OBJCOBJS): %.o: %.m
+ $(CXX) $(CFLAGS) -x objective-c++ $< -o $@
+
+TestGUI.app: TestGUI.app.in
+ rm -Rf TestGUI.app
+ mkdir -p TestGUI.app
+ cp -R TestGUI.app.in/ TestGUI.app
+
+clean:
+ rm -f $(OBJS) hidapi-testgui
+ rm -Rf TestGUI.app
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/testgui/Makefile.mingw b/c/src/third-party/hidapi/testgui/Makefile.mingw
new file mode 100644
index 000000000..df0f69d1d
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/Makefile.mingw
@@ -0,0 +1,32 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidapi-testgui
+
+CC=gcc
+CXX=g++
+COBJS=../windows/hid.o
+CPPOBJS=test.o
+OBJS=$(COBJS) $(CPPOBJS)
+CFLAGS=-I../hidapi -I../../hidapi-externals/fox/include -g -c
+LIBS= -mwindows -lsetupapi -L../../hidapi-externals/fox/lib -Wl,-Bstatic -lFOX-1.6 -Wl,-Bdynamic -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32
+
+
+hidapi-testgui: $(OBJS)
+ g++ -g $^ $(LIBS) -o hidapi-testgui
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+$(CPPOBJS): %.o: %.cpp
+ $(CXX) $(CFLAGS) $< -o $@
+
+clean:
+ rm -f *.o hidapi-testgui.exe
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Info.plist b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Info.plist
new file mode 100644
index 000000000..ab473d53a
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Info.plist
@@ -0,0 +1,28 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleDisplayName
+
+ CFBundleExecutable
+ hidapi-testgui
+ CFBundleIconFile
+ Signal11.icns
+ CFBundleIdentifier
+ us.signal11.hidtestgui
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ testgui
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ CSResourcesFileMapped
+
+
+
diff --git a/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/PkgInfo b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/PkgInfo
new file mode 100644
index 000000000..bd04210fb
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL????
\ No newline at end of file
diff --git a/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings
new file mode 100644
index 000000000..dea12de4c
Binary files /dev/null and b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/English.lproj/InfoPlist.strings differ
diff --git a/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns
new file mode 100644
index 000000000..bb6b7bd5f
Binary files /dev/null and b/c/src/third-party/hidapi/testgui/TestGUI.app.in/Contents/Resources/Signal11.icns differ
diff --git a/c/src/third-party/hidapi/testgui/copy_to_bundle.sh b/c/src/third-party/hidapi/testgui/copy_to_bundle.sh
new file mode 100755
index 000000000..6fa401dfb
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/copy_to_bundle.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+
+#### Configuration:
+# The name of the executable. It is assumed
+# that it is in the current working directory.
+EXE_NAME=hidapi-testgui
+# Path to the executable directory inside the bundle.
+# This must be an absolute path, so use $PWD.
+EXEPATH=$PWD/TestGUI.app/Contents/MacOS
+# Libraries to explicitly bundle, even though they
+# may not be in /opt/local. One per line. These
+# are used with grep, so only a portion of the name
+# is required. eg: libFOX, libz, etc.
+LIBS_TO_BUNDLE=libFOX
+
+
+function copydeps {
+ local file=$1
+ # echo "Copying deps for $file...."
+ local BASE_OF_EXE=`basename $file`
+
+ # A will contain the dependencies of this library
+ local A=`otool -LX $file |cut -f 1 -d " "`
+ local i
+ for i in $A; do
+ local BASE=`basename $i`
+
+ # See if it's a lib we specifically want to bundle
+ local bundle_this_lib=0
+ local j
+ for j in $LIBS_TO_BUNDLE; do
+ echo $i |grep -q $j
+ if [ $? -eq 0 ]; then
+ bundle_this_lib=1
+ echo "bundling $i because it's in the list."
+ break;
+ fi
+ done
+
+ # See if it's in /opt/local. Bundle all in /opt/local
+ local isOptLocal=0
+ echo $i |grep -q /opt/local
+ if [ $? -eq 0 ]; then
+ isOptLocal=1
+ echo "bundling $i because it's in /opt/local."
+ fi
+
+ # Bundle the library
+ if [ $isOptLocal -ne 0 ] || [ $bundle_this_lib -ne 0 ]; then
+
+ # Copy the file into the bundle if it exists.
+ if [ -f $EXEPATH/$BASE ]; then
+ z=0
+ else
+ cp $i $EXEPATH
+ chmod 755 $EXEPATH/$BASE
+ fi
+
+
+ # echo "$BASE_OF_EXE depends on $BASE"
+
+ # Fix the paths using install_name_tool and then
+ # call this function recursively for each dependency
+ # of this library.
+ if [ $BASE_OF_EXE != $BASE ]; then
+
+ # Fix the paths
+ install_name_tool -id @executable_path/$BASE $EXEPATH/$BASE
+ install_name_tool -change $i @executable_path/$BASE $EXEPATH/$BASE_OF_EXE
+
+ # Call this function (recursive) on
+ # on each dependency of this library.
+ copydeps $EXEPATH/$BASE
+ fi
+ fi
+ done
+}
+
+rm -f $EXEPATH/*
+
+# Copy the binary into the bundle. Use ../libtool to do this if it's
+# available because if $EXE_NAME was built with autotools, it will be
+# necessary. If ../libtool not available, just use cp to do the copy, but
+# only if $EXE_NAME is a binary.
+if [ -x ../libtool ]; then
+ ../libtool --mode=install cp $EXE_NAME $EXEPATH
+else
+ file -bI $EXE_NAME |grep binary
+ if [ $? -ne 0 ]; then
+ echo "There is no ../libtool and $EXE_NAME is not a binary."
+ echo "I'm not sure what to do."
+ exit 1
+ else
+ cp $EXE_NAME $EXEPATH
+ fi
+fi
+copydeps $EXEPATH/$EXE_NAME
diff --git a/c/src/third-party/hidapi/testgui/mac_support.h b/c/src/third-party/hidapi/testgui/mac_support.h
new file mode 100644
index 000000000..7d9ab493b
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/mac_support.h
@@ -0,0 +1,17 @@
+/*******************************
+ Mac support for HID Test GUI
+
+ Alan Ott
+ Signal 11 Software
+
+*******************************/
+
+#ifndef MAC_SUPPORT_H__
+#define MAC_SUPPORT_H__
+
+extern "C" {
+ void init_apple_message_system();
+ void check_apple_events();
+}
+
+#endif
diff --git a/c/src/third-party/hidapi/testgui/mac_support_cocoa.m b/c/src/third-party/hidapi/testgui/mac_support_cocoa.m
new file mode 100644
index 000000000..1b12163c0
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/mac_support_cocoa.m
@@ -0,0 +1,103 @@
+/*******************************
+ Mac support for HID Test GUI
+
+ Alan Ott
+ Signal 11 Software
+*******************************/
+
+#include
+#import
+
+#ifndef MAC_OS_X_VERSION_10_12
+#define MAC_OS_X_VERSION_10_12 101200
+#endif
+
+// macOS 10.12 deprecated NSAnyEventMask in favor of NSEventMaskAny
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
+#define NSEventMaskAny NSAnyEventMask
+#endif
+
+extern FXMainWindow *g_main_window;
+
+
+@interface MyAppDelegate : NSObject
+{
+}
+@end
+
+@implementation MyAppDelegate
+- (void) applicationWillBecomeActive:(NSNotification*)notif
+{
+ printf("WillBecomeActive\n");
+ g_main_window->show();
+
+}
+
+- (void) applicationWillTerminate:(NSNotification*)notif
+{
+ /* Doesn't get called. Not sure why */
+ printf("WillTerminate\n");
+ FXApp::instance()->exit();
+}
+
+- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*)sender
+{
+ /* Doesn't get called. Not sure why */
+ printf("ShouldTerminate\n");
+ return YES;
+}
+
+- (void) applicationWillHide:(NSNotification*)notif
+{
+ printf("WillHide\n");
+ g_main_window->hide();
+}
+
+- (void) handleQuitEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
+{
+ printf("QuitEvent\n");
+ FXApp::instance()->exit();
+}
+
+@end
+
+extern "C" {
+
+void
+init_apple_message_system()
+{
+ static MyAppDelegate *d = [MyAppDelegate new];
+
+ [[NSApplication sharedApplication] setDelegate:d];
+
+ /* Register for Apple Events. */
+ /* This is from
+ http://stackoverflow.com/questions/1768497/application-exit-event */
+ NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
+ [aem setEventHandler:d
+ andSelector:@selector(handleQuitEvent:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
+}
+
+void
+check_apple_events()
+{
+ NSApplication *app = [NSApplication sharedApplication];
+
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ while (1) {
+ NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event == NULL)
+ break;
+ else {
+ //printf("Event happened: Type: %d\n", event->_type);
+ [app sendEvent: event];
+ }
+ }
+ [pool release];
+}
+
+} /* extern "C" */
diff --git a/c/src/third-party/hidapi/testgui/test.cpp b/c/src/third-party/hidapi/testgui/test.cpp
new file mode 100644
index 000000000..538db7917
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/test.cpp
@@ -0,0 +1,532 @@
+/*******************************************************
+ Demo Program for HIDAPI
+
+ Alan Ott
+ Signal 11 Software
+
+ 2010-07-20
+
+ Copyright 2010, All Rights Reserved
+
+ This contents of this file may be used by anyone
+ for any reason without any conditions and may be
+ used as a starting point for your own applications
+ which use HIDAPI.
+********************************************************/
+
+
+#include
+
+#include "hidapi.h"
+#include "mac_support.h"
+#include
+#include
+#include
+
+#ifdef _WIN32
+ // Thanks Microsoft, but I know how to use strncpy().
+ #pragma warning(disable:4996)
+#endif
+
+class MainWindow : public FXMainWindow {
+ FXDECLARE(MainWindow)
+
+public:
+ enum {
+ ID_FIRST = FXMainWindow::ID_LAST,
+ ID_CONNECT,
+ ID_DISCONNECT,
+ ID_RESCAN,
+ ID_SEND_OUTPUT_REPORT,
+ ID_SEND_FEATURE_REPORT,
+ ID_GET_FEATURE_REPORT,
+ ID_CLEAR,
+ ID_TIMER,
+ ID_MAC_TIMER,
+ ID_LAST,
+ };
+
+private:
+ FXList *device_list;
+ FXButton *connect_button;
+ FXButton *disconnect_button;
+ FXButton *rescan_button;
+ FXButton *output_button;
+ FXLabel *connected_label;
+ FXTextField *output_text;
+ FXTextField *output_len;
+ FXButton *feature_button;
+ FXButton *get_feature_button;
+ FXTextField *feature_text;
+ FXTextField *feature_len;
+ FXTextField *get_feature_text;
+ FXText *input_text;
+ FXFont *title_font;
+
+ struct hid_device_info *devices;
+ hid_device *connected_device;
+ size_t getDataFromTextField(FXTextField *tf, char *buf, size_t len);
+ int getLengthFromTextField(FXTextField *tf);
+
+
+protected:
+ MainWindow() {};
+public:
+ MainWindow(FXApp *a);
+ ~MainWindow();
+ virtual void create();
+
+ long onConnect(FXObject *sender, FXSelector sel, void *ptr);
+ long onDisconnect(FXObject *sender, FXSelector sel, void *ptr);
+ long onRescan(FXObject *sender, FXSelector sel, void *ptr);
+ long onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr);
+ long onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
+ long onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
+ long onClear(FXObject *sender, FXSelector sel, void *ptr);
+ long onTimeout(FXObject *sender, FXSelector sel, void *ptr);
+ long onMacTimeout(FXObject *sender, FXSelector sel, void *ptr);
+};
+
+// FOX 1.7 changes the timeouts to all be nanoseconds.
+// Fox 1.6 had all timeouts as milliseconds.
+#if (FOX_MINOR >= 7)
+ const int timeout_scalar = 1000*1000;
+#else
+ const int timeout_scalar = 1;
+#endif
+
+FXMainWindow *g_main_window;
+
+
+FXDEFMAP(MainWindow) MainWindowMap [] = {
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_RESCAN, MainWindow::onRescan ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_OUTPUT_REPORT, MainWindow::onSendOutputReport ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_GET_FEATURE_REPORT, MainWindow::onGetFeatureReport ),
+ FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
+ FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
+ FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
+};
+
+FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
+
+MainWindow::MainWindow(FXApp *app)
+ : FXMainWindow(app, "HIDAPI Test Application", NULL, NULL, DECOR_ALL, 200,100, 425,700)
+{
+ devices = NULL;
+ connected_device = NULL;
+
+ FXVerticalFrame *vf = new FXVerticalFrame(this, LAYOUT_FILL_Y|LAYOUT_FILL_X);
+
+ FXLabel *label = new FXLabel(vf, "HIDAPI Test Tool");
+ title_font = new FXFont(getApp(), "Arial", 14, FXFont::Bold);
+ label->setFont(title_font);
+
+ new FXLabel(vf,
+ "Select a device and press Connect.", NULL, JUSTIFY_LEFT);
+ new FXLabel(vf,
+ "Output data bytes can be entered in the Output section, \n"
+ "separated by space, comma or brackets. Data starting with 0x\n"
+ "is treated as hex. Data beginning with a 0 is treated as \n"
+ "octal. All other data is treated as decimal.", NULL, JUSTIFY_LEFT);
+ new FXLabel(vf,
+ "Data received from the device appears in the Input section.",
+ NULL, JUSTIFY_LEFT);
+ new FXLabel(vf,
+ "Optionally, a report length may be specified. Extra bytes are\n"
+ "padded with zeros. If no length is specified, the length is \n"
+ "inferred from the data.",
+ NULL, JUSTIFY_LEFT);
+ new FXLabel(vf, "");
+
+ // Device List and Connect/Disconnect buttons
+ FXHorizontalFrame *hf = new FXHorizontalFrame(vf, LAYOUT_FILL_X);
+ //device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0,0,300,200);
+ device_list = new FXList(new FXHorizontalFrame(hf,FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0), NULL, 0, LISTBOX_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,300,200);
+ FXVerticalFrame *buttonVF = new FXVerticalFrame(hf);
+ connect_button = new FXButton(buttonVF, "Connect", NULL, this, ID_CONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
+ disconnect_button = new FXButton(buttonVF, "Disconnect", NULL, this, ID_DISCONNECT, BUTTON_NORMAL|LAYOUT_FILL_X);
+ disconnect_button->disable();
+ rescan_button = new FXButton(buttonVF, "Re-Scan devices", NULL, this, ID_RESCAN, BUTTON_NORMAL|LAYOUT_FILL_X);
+ new FXHorizontalFrame(buttonVF, 0, 0,0,0,0, 0,0,50,0);
+
+ connected_label = new FXLabel(vf, "Disconnected");
+
+ new FXHorizontalFrame(vf);
+
+ // Output Group Box
+ FXGroupBox *gb = new FXGroupBox(vf, "Output", FRAME_GROOVE|LAYOUT_FILL_X);
+ FXMatrix *matrix = new FXMatrix(gb, 3, MATRIX_BY_COLUMNS|LAYOUT_FILL_X);
+ new FXLabel(matrix, "Data");
+ new FXLabel(matrix, "Length");
+ new FXLabel(matrix, "");
+
+ //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
+ output_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
+ output_text->setText("1 0x81 0");
+ output_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
+ output_button = new FXButton(matrix, "Send Output Report", NULL, this, ID_SEND_OUTPUT_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
+ output_button->disable();
+ //new FXHorizontalFrame(matrix, LAYOUT_FILL_X);
+
+ //hf = new FXHorizontalFrame(gb, LAYOUT_FILL_X);
+ feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
+ feature_len = new FXTextField(matrix, 5, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
+ feature_button = new FXButton(matrix, "Send Feature Report", NULL, this, ID_SEND_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
+ feature_button->disable();
+
+ get_feature_text = new FXTextField(matrix, 30, NULL, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN);
+ new FXWindow(matrix);
+ get_feature_button = new FXButton(matrix, "Get Feature Report", NULL, this, ID_GET_FEATURE_REPORT, BUTTON_NORMAL|LAYOUT_FILL_X);
+ get_feature_button->disable();
+
+
+ // Input Group Box
+ gb = new FXGroupBox(vf, "Input", FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y);
+ FXVerticalFrame *innerVF = new FXVerticalFrame(gb, LAYOUT_FILL_X|LAYOUT_FILL_Y);
+ input_text = new FXText(new FXHorizontalFrame(innerVF,LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0), NULL, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y);
+ input_text->setEditable(false);
+ new FXButton(innerVF, "Clear", NULL, this, ID_CLEAR, BUTTON_NORMAL|LAYOUT_RIGHT);
+
+
+}
+
+MainWindow::~MainWindow()
+{
+ if (connected_device)
+ hid_close(connected_device);
+ hid_exit();
+ delete title_font;
+}
+
+void
+MainWindow::create()
+{
+ FXMainWindow::create();
+ show();
+
+ onRescan(NULL, 0, NULL);
+
+
+#ifdef __APPLE__
+ init_apple_message_system();
+#endif
+
+ getApp()->addTimeout(this, ID_MAC_TIMER,
+ 50 * timeout_scalar /*50ms*/);
+}
+
+long
+MainWindow::onConnect(FXObject *sender, FXSelector sel, void *ptr)
+{
+ if (connected_device != NULL)
+ return 1;
+
+ FXint cur_item = device_list->getCurrentItem();
+ if (cur_item < 0)
+ return -1;
+ FXListItem *item = device_list->getItem(cur_item);
+ if (!item)
+ return -1;
+ struct hid_device_info *device_info = (struct hid_device_info*) item->getData();
+ if (!device_info)
+ return -1;
+
+ connected_device = hid_open_path(device_info->path);
+
+ if (!connected_device) {
+ FXMessageBox::error(this, MBOX_OK, "Device Error", "Unable To Connect to Device");
+ return -1;
+ }
+
+ hid_set_nonblocking(connected_device, 1);
+
+ getApp()->addTimeout(this, ID_TIMER,
+ 5 * timeout_scalar /*5ms*/);
+
+ FXString s;
+ s.format("Connected to: %04hx:%04hx -", device_info->vendor_id, device_info->product_id);
+ s += FXString(" ") + device_info->manufacturer_string;
+ s += FXString(" ") + device_info->product_string;
+ connected_label->setText(s);
+ output_button->enable();
+ feature_button->enable();
+ get_feature_button->enable();
+ connect_button->disable();
+ disconnect_button->enable();
+ input_text->setText("");
+
+
+ return 1;
+}
+
+long
+MainWindow::onDisconnect(FXObject *sender, FXSelector sel, void *ptr)
+{
+ hid_close(connected_device);
+ connected_device = NULL;
+ connected_label->setText("Disconnected");
+ output_button->disable();
+ feature_button->disable();
+ get_feature_button->disable();
+ connect_button->enable();
+ disconnect_button->disable();
+
+ getApp()->removeTimeout(this, ID_TIMER);
+
+ return 1;
+}
+
+long
+MainWindow::onRescan(FXObject *sender, FXSelector sel, void *ptr)
+{
+ struct hid_device_info *cur_dev;
+
+ device_list->clearItems();
+
+ // List the Devices
+ hid_free_enumeration(devices);
+ devices = hid_enumerate(0x0, 0x0);
+ cur_dev = devices;
+ while (cur_dev) {
+ // Add it to the List Box.
+ FXString s;
+ FXString usage_str;
+ s.format("%04hx:%04hx -", cur_dev->vendor_id, cur_dev->product_id);
+ s += FXString(" ") + cur_dev->manufacturer_string;
+ s += FXString(" ") + cur_dev->product_string;
+ usage_str.format(" (usage: %04hx:%04hx) ", cur_dev->usage_page, cur_dev->usage);
+ s += usage_str;
+ FXListItem *li = new FXListItem(s, NULL, cur_dev);
+ device_list->appendItem(li);
+
+ cur_dev = cur_dev->next;
+ }
+
+ if (device_list->getNumItems() == 0)
+ device_list->appendItem("*** No Devices Connected ***");
+ else {
+ device_list->selectItem(0);
+ }
+
+ return 1;
+}
+
+size_t
+MainWindow::getDataFromTextField(FXTextField *tf, char *buf, size_t len)
+{
+ const char *delim = " ,{}\t\r\n";
+ FXString data = tf->getText();
+ const FXchar *d = data.text();
+ size_t i = 0;
+
+ // Copy the string from the GUI.
+ size_t sz = strlen(d);
+ char *str = (char*) malloc(sz+1);
+ strcpy(str, d);
+
+ // For each token in the string, parse and store in buf[].
+ char *token = strtok(str, delim);
+ while (token) {
+ char *endptr;
+ long int val = strtol(token, &endptr, 0);
+ buf[i++] = val;
+ token = strtok(NULL, delim);
+ }
+
+ free(str);
+ return i;
+}
+
+/* getLengthFromTextField()
+ Returns length:
+ 0: empty text field
+ >0: valid length
+ -1: invalid length */
+int
+MainWindow::getLengthFromTextField(FXTextField *tf)
+{
+ long int len;
+ FXString str = tf->getText();
+ size_t sz = str.length();
+
+ if (sz > 0) {
+ char *endptr;
+ len = strtol(str.text(), &endptr, 0);
+ if (endptr != str.text() && *endptr == '\0') {
+ if (len <= 0) {
+ FXMessageBox::error(this, MBOX_OK, "Invalid length", "Enter a length greater than zero.");
+ return -1;
+ }
+ return len;
+ }
+ else
+ return -1;
+ }
+
+ return 0;
+}
+
+long
+MainWindow::onSendOutputReport(FXObject *sender, FXSelector sel, void *ptr)
+{
+ char buf[256];
+ size_t data_len, len;
+ int textfield_len;
+
+ memset(buf, 0x0, sizeof(buf));
+ textfield_len = getLengthFromTextField(output_len);
+ data_len = getDataFromTextField(output_text, buf, sizeof(buf));
+
+ if (textfield_len < 0) {
+ FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
+ return 1;
+ }
+
+ if (textfield_len > sizeof(buf)) {
+ FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
+ return 1;
+ }
+
+ len = (textfield_len)? textfield_len: data_len;
+
+ int res = hid_write(connected_device, (const unsigned char*)buf, len);
+ if (res < 0) {
+ FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not write to device. Error reported was: %ls", hid_error(connected_device));
+ }
+
+ return 1;
+}
+
+long
+MainWindow::onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
+{
+ char buf[256];
+ size_t data_len, len;
+ int textfield_len;
+
+ memset(buf, 0x0, sizeof(buf));
+ textfield_len = getLengthFromTextField(feature_len);
+ data_len = getDataFromTextField(feature_text, buf, sizeof(buf));
+
+ if (textfield_len < 0) {
+ FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is invalid. Please enter a number in hex, octal, or decimal.");
+ return 1;
+ }
+
+ if (textfield_len > sizeof(buf)) {
+ FXMessageBox::error(this, MBOX_OK, "Invalid length", "Length field is too long.");
+ return 1;
+ }
+
+ len = (textfield_len)? textfield_len: data_len;
+
+ int res = hid_send_feature_report(connected_device, (const unsigned char*)buf, len);
+ if (res < 0) {
+ FXMessageBox::error(this, MBOX_OK, "Error Writing", "Could not send feature report to device. Error reported was: %ls", hid_error(connected_device));
+ }
+
+ return 1;
+}
+
+long
+MainWindow::onGetFeatureReport(FXObject *sender, FXSelector sel, void *ptr)
+{
+ char buf[256];
+ size_t len;
+
+ memset(buf, 0x0, sizeof(buf));
+ len = getDataFromTextField(get_feature_text, buf, sizeof(buf));
+
+ if (len != 1) {
+ FXMessageBox::error(this, MBOX_OK, "Too many numbers", "Enter only a single report number in the text field");
+ }
+
+ int res = hid_get_feature_report(connected_device, (unsigned char*)buf, sizeof(buf));
+ if (res < 0) {
+ FXMessageBox::error(this, MBOX_OK, "Error Getting Report", "Could not get feature report from device. Error reported was: %ls", hid_error(connected_device));
+ }
+
+ if (res > 0) {
+ FXString s;
+ s.format("Returned Feature Report. %d bytes:\n", res);
+ for (int i = 0; i < res; i++) {
+ FXString t;
+ t.format("%02hhx ", buf[i]);
+ s += t;
+ if ((i+1) % 4 == 0)
+ s += " ";
+ if ((i+1) % 16 == 0)
+ s += "\n";
+ }
+ s += "\n";
+ input_text->appendText(s);
+ input_text->setBottomLine(INT_MAX);
+ }
+
+ return 1;
+}
+
+long
+MainWindow::onClear(FXObject *sender, FXSelector sel, void *ptr)
+{
+ input_text->setText("");
+ return 1;
+}
+
+long
+MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
+{
+ unsigned char buf[256];
+ int res = hid_read(connected_device, buf, sizeof(buf));
+
+ if (res > 0) {
+ FXString s;
+ s.format("Received %d bytes:\n", res);
+ for (int i = 0; i < res; i++) {
+ FXString t;
+ t.format("%02hhx ", buf[i]);
+ s += t;
+ if ((i+1) % 4 == 0)
+ s += " ";
+ if ((i+1) % 16 == 0)
+ s += "\n";
+ }
+ s += "\n";
+ input_text->appendText(s);
+ input_text->setBottomLine(INT_MAX);
+ }
+ if (res < 0) {
+ input_text->appendText("hid_read() returned error\n");
+ input_text->setBottomLine(INT_MAX);
+ }
+
+ getApp()->addTimeout(this, ID_TIMER,
+ 5 * timeout_scalar /*5ms*/);
+ return 1;
+}
+
+long
+MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
+{
+#ifdef __APPLE__
+ check_apple_events();
+
+ getApp()->addTimeout(this, ID_MAC_TIMER,
+ 50 * timeout_scalar /*50ms*/);
+#endif
+
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ FXApp app("HIDAPI Test Application", "Signal 11 Software");
+ app.init(argc, argv);
+ g_main_window = new MainWindow(&app);
+ app.create();
+ app.run();
+ return 0;
+}
diff --git a/c/src/third-party/hidapi/testgui/testgui.sln b/c/src/third-party/hidapi/testgui/testgui.sln
new file mode 100644
index 000000000..56be6c6a5
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/testgui.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgui", "testgui.vcproj", "{08769AC3-785A-4DDC-BFC7-1775414B7AB7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Debug|Win32.Build.0 = Debug|Win32
+ {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.ActiveCfg = Release|Win32
+ {08769AC3-785A-4DDC-BFC7-1775414B7AB7}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/c/src/third-party/hidapi/testgui/testgui.vcproj b/c/src/third-party/hidapi/testgui/testgui.vcproj
new file mode 100644
index 000000000..0f73a013f
--- /dev/null
+++ b/c/src/third-party/hidapi/testgui/testgui.vcproj
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/third-party/hidapi/udev/99-hid.rules b/c/src/third-party/hidapi/udev/99-hid.rules
new file mode 100644
index 000000000..0385f50b0
--- /dev/null
+++ b/c/src/third-party/hidapi/udev/99-hid.rules
@@ -0,0 +1,33 @@
+# This is a sample udev file for HIDAPI devices which changes the permissions
+# to 0666 (world readable/writable) for a specified device on Linux systems.
+
+
+# If you are using the libusb implementation of hidapi (libusb/hid.c), then
+# use something like the following line, substituting the VID and PID with
+# those of your device. Note that for kernels before 2.6.24, you will need
+# to substitute "usb" with "usb_device". It shouldn't hurt to use two lines
+# (one each way) for compatibility with older systems.
+
+# HIDAPI/libusb
+SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
+
+
+# If you are using the hidraw implementation (linux/hid.c), then do something
+# like the following, substituting the VID and PID with your device. Busnum 1
+# is USB.
+
+# HIDAPI/hidraw
+KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666"
+
+# Once done, optionally rename this file for your device, and drop it into
+# /etc/udev/rules.d and unplug and re-plug your device. This is all that is
+# necessary to see the new permissions. Udev does not have to be restarted.
+
+# Note that the hexadecimal values for VID and PID are case sensitive and
+# must be lower case.
+
+# If you think permissions of 0666 are too loose, then see:
+# http://reactivated.net/writing_udev_rules.html for more information on finer
+# grained permission setting. For example, it might be sufficient to just
+# set the group or user owner for specific devices (for example the plugdev
+# group on some systems).
diff --git a/c/src/third-party/hidapi/windows/.gitignore b/c/src/third-party/hidapi/windows/.gitignore
new file mode 100644
index 000000000..c2ad395ec
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/.gitignore
@@ -0,0 +1,17 @@
+Debug
+Release
+.vs/
+*.exp
+*.ilk
+*.lib
+*.suo
+*.vcproj.*
+*.vcxproj.*
+*.ncb
+*.suo
+*.dll
+*.pdb
+.deps
+.libs
+*.lo
+*.la
diff --git a/c/src/third-party/hidapi/windows/Makefile-manual b/c/src/third-party/hidapi/windows/Makefile-manual
new file mode 100644
index 000000000..ac471d66d
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/Makefile-manual
@@ -0,0 +1,14 @@
+
+
+OS=$(shell uname)
+
+ifneq (,$(findstring MINGW,$(OS)))
+ FILE=Makefile.mingw
+endif
+
+ifeq ($(FILE), )
+all:
+ $(error Your platform ${OS} is not supported at this time.)
+endif
+
+include $(FILE)
diff --git a/c/src/third-party/hidapi/windows/Makefile.am b/c/src/third-party/hidapi/windows/Makefile.am
new file mode 100644
index 000000000..97e261ac9
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/Makefile.am
@@ -0,0 +1,16 @@
+lib_LTLIBRARIES = libhidapi.la
+libhidapi_la_SOURCES = hid.c
+libhidapi_la_LDFLAGS = $(LTLDFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/hidapi/
+libhidapi_la_LIBADD = $(LIBS)
+
+hdrdir = $(includedir)/hidapi
+hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h
+
+EXTRA_DIST = \
+ ddk_build \
+ hidapi.vcproj \
+ hidtest.vcproj \
+ Makefile-manual \
+ Makefile.mingw \
+ hidapi.sln
diff --git a/c/src/third-party/hidapi/windows/Makefile.mingw b/c/src/third-party/hidapi/windows/Makefile.mingw
new file mode 100644
index 000000000..2407158b3
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/Makefile.mingw
@@ -0,0 +1,30 @@
+###########################################
+# Simple Makefile for HIDAPI test program
+#
+# Alan Ott
+# Signal 11 Software
+# 2010-06-01
+###########################################
+
+all: hidtest libhidapi.dll
+
+CC=gcc
+COBJS=hid.o ../hidtest/test.o
+OBJS=$(COBJS)
+CFLAGS=-I../hidapi -g -c
+LIBS= -lsetupapi
+DLL_LDFLAGS = -mwindows -lsetupapi
+
+hidtest: $(OBJS)
+ $(CC) -g $^ $(LIBS) -o hidtest
+
+libhidapi.dll: $(OBJS)
+ $(CC) -g $^ $(DLL_LDFLAGS) -o libhidapi.dll
+
+$(COBJS): %.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm *.o ../hidtest/*.o hidtest.exe
+
+.PHONY: clean
diff --git a/c/src/third-party/hidapi/windows/ddk_build/.gitignore b/c/src/third-party/hidapi/windows/ddk_build/.gitignore
new file mode 100644
index 000000000..823ff0b2c
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/ddk_build/.gitignore
@@ -0,0 +1,2 @@
+*.log
+obj*_*_*
\ No newline at end of file
diff --git a/c/src/third-party/hidapi/windows/ddk_build/hidapi.def b/c/src/third-party/hidapi/windows/ddk_build/hidapi.def
new file mode 100644
index 000000000..01fe47d64
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/ddk_build/hidapi.def
@@ -0,0 +1,18 @@
+LIBRARY hidapi
+EXPORTS
+ hid_open @1
+ hid_write @2
+ hid_read @3
+ hid_close @4
+ hid_get_product_string @5
+ hid_get_manufacturer_string @6
+ hid_get_serial_number_string @7
+ hid_get_indexed_string @8
+ hid_error @9
+ hid_set_nonblocking @10
+ hid_enumerate @11
+ hid_open_path @12
+ hid_send_feature_report @13
+ hid_get_feature_report @14
+ hid_get_input_report @15
+
\ No newline at end of file
diff --git a/c/src/third-party/hidapi/windows/ddk_build/sources b/c/src/third-party/hidapi/windows/ddk_build/sources
new file mode 100644
index 000000000..7f06a0963
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/ddk_build/sources
@@ -0,0 +1,23 @@
+TARGETNAME=hidapi
+TARGETTYPE=DYNLINK
+UMTYPE=console
+UMENTRY=main
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+TARGETLIBS=$(SDK_LIB_PATH)\hid.lib \
+ $(SDK_LIB_PATH)\setupapi.lib \
+ $(SDK_LIB_PATH)\kernel32.lib \
+ $(SDK_LIB_PATH)\comdlg32.lib
+
+USE_MSVCRT=1
+
+INCLUDES= ..\..\hidapi
+SOURCES= ..\hid.c \
+
+
+TARGET_DESTINATION=retail
+
+MUI=0
+MUI_COMMENT="HID Interface DLL"
+
diff --git a/c/src/third-party/hidapi/windows/hid.c b/c/src/third-party/hidapi/windows/hid.c
new file mode 100755
index 000000000..799b35550
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hid.c
@@ -0,0 +1,1019 @@
+/*******************************************************
+ HIDAPI - Multi-Platform library for
+ communication with HID devices.
+
+ Alan Ott
+ Signal 11 Software
+
+ 8/22/2009
+
+ Copyright 2009, All Rights Reserved.
+
+ At the discretion of the user of this library,
+ this software may be licensed under the terms of the
+ GNU General Public License v3, a BSD-Style license, or the
+ original HIDAPI license as outlined in the LICENSE.txt,
+ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
+ files located at the root of the source distribution.
+ These files may also be found in the public source
+ code repository located at:
+ https://github.com/libusb/hidapi .
+********************************************************/
+
+#include
+
+#ifndef _NTDEF_
+typedef LONG NTSTATUS;
+#endif
+
+#ifdef __MINGW32__
+#include
+#include
+#endif
+
+#ifdef __CYGWIN__
+#include
+#define _wcsdup wcsdup
+#endif
+
+/* The maximum number of characters that can be passed into the
+ HidD_Get*String() functions without it failing.*/
+#define MAX_STRING_WCHARS 0xFFF
+
+/*#define HIDAPI_USE_DDK*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ #include
+ #include
+ #ifdef HIDAPI_USE_DDK
+ #include
+ #endif
+
+ /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
+ #define HID_OUT_CTL_CODE(id) \
+ CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+ #define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
+ #define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include
+#include
+
+
+#include "hidapi.h"
+
+#undef MIN
+#define MIN(x,y) ((x) < (y)? (x): (y))
+
+#ifdef _MSC_VER
+ /* Thanks Microsoft, but I know how to use strncpy(). */
+ #pragma warning(disable:4996)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HIDAPI_USE_DDK
+ /* Since we're not building with the DDK, and the HID header
+ files aren't part of the SDK, we have to define all this
+ stuff here. In lookup_functions(), the function pointers
+ defined below are set. */
+ typedef struct _HIDD_ATTRIBUTES{
+ ULONG Size;
+ USHORT VendorID;
+ USHORT ProductID;
+ USHORT VersionNumber;
+ } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
+
+ typedef USHORT USAGE;
+ typedef struct _HIDP_CAPS {
+ USAGE Usage;
+ USAGE UsagePage;
+ USHORT InputReportByteLength;
+ USHORT OutputReportByteLength;
+ USHORT FeatureReportByteLength;
+ USHORT Reserved[17];
+ USHORT fields_not_used_by_hidapi[10];
+ } HIDP_CAPS, *PHIDP_CAPS;
+ typedef void* PHIDP_PREPARSED_DATA;
+ #define HIDP_STATUS_SUCCESS 0x110000
+
+ typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
+ typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
+ typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
+ typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
+ typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
+ typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
+ typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length);
+ typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
+ typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
+ typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
+ typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
+ typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
+
+ static HidD_GetAttributes_ HidD_GetAttributes;
+ static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
+ static HidD_GetManufacturerString_ HidD_GetManufacturerString;
+ static HidD_GetProductString_ HidD_GetProductString;
+ static HidD_SetFeature_ HidD_SetFeature;
+ static HidD_GetFeature_ HidD_GetFeature;
+ static HidD_GetInputReport_ HidD_GetInputReport;
+ static HidD_GetIndexedString_ HidD_GetIndexedString;
+ static HidD_GetPreparsedData_ HidD_GetPreparsedData;
+ static HidD_FreePreparsedData_ HidD_FreePreparsedData;
+ static HidP_GetCaps_ HidP_GetCaps;
+ static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
+
+ static HMODULE lib_handle = NULL;
+ static BOOLEAN initialized = FALSE;
+#endif /* HIDAPI_USE_DDK */
+
+struct hid_device_ {
+ HANDLE device_handle;
+ BOOL blocking;
+ USHORT output_report_length;
+ size_t input_report_length;
+ void *last_error_str;
+ DWORD last_error_num;
+ BOOL read_pending;
+ char *read_buf;
+ OVERLAPPED ol;
+};
+
+static hid_device *new_hid_device()
+{
+ hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
+ dev->device_handle = INVALID_HANDLE_VALUE;
+ dev->blocking = TRUE;
+ dev->output_report_length = 0;
+ dev->input_report_length = 0;
+ dev->last_error_str = NULL;
+ dev->last_error_num = 0;
+ dev->read_pending = FALSE;
+ dev->read_buf = NULL;
+ memset(&dev->ol, 0, sizeof(dev->ol));
+ dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
+
+ return dev;
+}
+
+static void free_hid_device(hid_device *dev)
+{
+ CloseHandle(dev->ol.hEvent);
+ CloseHandle(dev->device_handle);
+ LocalFree(dev->last_error_str);
+ free(dev->read_buf);
+ free(dev);
+}
+
+static void register_error(hid_device *dev, const char *op)
+{
+ WCHAR *ptr, *msg;
+
+ FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPVOID)&msg, 0/*sz*/,
+ NULL);
+
+ /* Get rid of the CR and LF that FormatMessage() sticks at the
+ end of the message. Thanks Microsoft! */
+ ptr = msg;
+ while (*ptr) {
+ if (*ptr == '\r') {
+ *ptr = 0x0000;
+ break;
+ }
+ ptr++;
+ }
+
+ /* Store the message off in the Device entry so that
+ the hid_error() function can pick it up. */
+ LocalFree(dev->last_error_str);
+ dev->last_error_str = msg;
+}
+
+#ifndef HIDAPI_USE_DDK
+static int lookup_functions()
+{
+ lib_handle = LoadLibraryA("hid.dll");
+ if (lib_handle) {
+#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
+ RESOLVE(HidD_GetAttributes);
+ RESOLVE(HidD_GetSerialNumberString);
+ RESOLVE(HidD_GetManufacturerString);
+ RESOLVE(HidD_GetProductString);
+ RESOLVE(HidD_SetFeature);
+ RESOLVE(HidD_GetFeature);
+ RESOLVE(HidD_GetInputReport);
+ RESOLVE(HidD_GetIndexedString);
+ RESOLVE(HidD_GetPreparsedData);
+ RESOLVE(HidD_FreePreparsedData);
+ RESOLVE(HidP_GetCaps);
+ RESOLVE(HidD_SetNumInputBuffers);
+#undef RESOLVE
+ }
+ else
+ return -1;
+
+ return 0;
+}
+#endif
+
+static HANDLE open_device(const char *path, BOOL open_rw)
+{
+ HANDLE handle;
+ DWORD desired_access = (open_rw)? (GENERIC_WRITE | GENERIC_READ): 0;
+ DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+
+ handle = CreateFileA(path,
+ desired_access,
+ share_mode,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
+ 0);
+
+ return handle;
+}
+
+int HID_API_EXPORT hid_init(void)
+{
+#ifndef HIDAPI_USE_DDK
+ if (!initialized) {
+ if (lookup_functions() < 0) {
+ hid_exit();
+ return -1;
+ }
+ initialized = TRUE;
+ }
+#endif
+ return 0;
+}
+
+int HID_API_EXPORT hid_exit(void)
+{
+#ifndef HIDAPI_USE_DDK
+ if (lib_handle)
+ FreeLibrary(lib_handle);
+ lib_handle = NULL;
+ initialized = FALSE;
+#endif
+ return 0;
+}
+
+struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
+{
+ BOOL res;
+ struct hid_device_info *root = NULL; /* return object */
+ struct hid_device_info *cur_dev = NULL;
+
+ /* Windows objects for interacting with the driver. */
+ GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
+ SP_DEVINFO_DATA devinfo_data;
+ SP_DEVICE_INTERFACE_DATA device_interface_data;
+ SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
+ HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
+ int device_index = 0;
+ int i;
+
+ if (hid_init() < 0)
+ return NULL;
+
+ /* Initialize the Windows objects. */
+ memset(&devinfo_data, 0x0, sizeof(devinfo_data));
+ devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ /* Get information for all the devices belonging to the HID class. */
+ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+ /* Iterate over each device in the HID class, looking for the right one. */
+
+ for (;;) {
+ HANDLE write_handle = INVALID_HANDLE_VALUE;
+ DWORD required_size = 0;
+ HIDD_ATTRIBUTES attrib;
+
+ res = SetupDiEnumDeviceInterfaces(device_info_set,
+ NULL,
+ &InterfaceClassGuid,
+ device_index,
+ &device_interface_data);
+
+ if (!res) {
+ /* A return of FALSE from this function means that
+ there are no more devices. */
+ break;
+ }
+
+ /* Call with 0-sized detail size, and let the function
+ tell us how long the detail struct needs to be. The
+ size is put in &required_size. */
+ res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
+ &device_interface_data,
+ NULL,
+ 0,
+ &required_size,
+ NULL);
+
+ /* Allocate a long enough structure for device_interface_detail_data. */
+ device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
+ device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
+
+ /* Get the detailed data for this device. The detail data gives us
+ the device path for this device, which is then passed into
+ CreateFile() to get a handle to the device. */
+ res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
+ &device_interface_data,
+ device_interface_detail_data,
+ required_size,
+ NULL,
+ NULL);
+
+ if (!res) {
+ /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
+ Continue to the next device. */
+ goto cont;
+ }
+
+ /* Make sure this device is of Setup Class "HIDClass" and has a
+ driver bound to it. */
+ for (i = 0; ; i++) {
+ char driver_name[256];
+
+ /* Populate devinfo_data. This function will return failure
+ when there are no more interfaces left. */
+ res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
+ if (!res)
+ goto cont;
+
+ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
+ SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
+ if (!res)
+ goto cont;
+
+ if ((strcmp(driver_name, "HIDClass") == 0) ||
+ (strcmp(driver_name, "Mouse") == 0) ||
+ (strcmp(driver_name, "Keyboard") == 0)) {
+ /* See if there's a driver bound. */
+ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
+ SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
+ if (res)
+ break;
+ }
+ }
+
+ //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
+
+ /* Open a handle to the device */
+ write_handle = open_device(device_interface_detail_data->DevicePath, FALSE);
+
+ /* Check validity of write_handle. */
+ if (write_handle == INVALID_HANDLE_VALUE) {
+ /* Unable to open the device. */
+ //register_error(dev, "CreateFile");
+ goto cont_close;
+ }
+
+
+ /* Get the Vendor ID and Product ID for this device. */
+ attrib.Size = sizeof(HIDD_ATTRIBUTES);
+ HidD_GetAttributes(write_handle, &attrib);
+ //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
+
+ /* Check the VID/PID to see if we should add this
+ device to the enumeration list. */
+ if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
+ (product_id == 0x0 || attrib.ProductID == product_id)) {
+
+ #define WSTR_LEN 512
+ const char *str;
+ struct hid_device_info *tmp;
+ PHIDP_PREPARSED_DATA pp_data = NULL;
+ HIDP_CAPS caps;
+ BOOLEAN res;
+ NTSTATUS nt_res;
+ wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
+ size_t len;
+
+ /* VID/PID match. Create the record. */
+ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
+ if (cur_dev) {
+ cur_dev->next = tmp;
+ }
+ else {
+ root = tmp;
+ }
+ cur_dev = tmp;
+
+ /* Get the Usage Page and Usage for this device. */
+ res = HidD_GetPreparsedData(write_handle, &pp_data);
+ if (res) {
+ nt_res = HidP_GetCaps(pp_data, &caps);
+ if (nt_res == HIDP_STATUS_SUCCESS) {
+ cur_dev->usage_page = caps.UsagePage;
+ cur_dev->usage = caps.Usage;
+ }
+
+ HidD_FreePreparsedData(pp_data);
+ }
+
+ /* Fill out the record */
+ cur_dev->next = NULL;
+ str = device_interface_detail_data->DevicePath;
+ if (str) {
+ len = strlen(str);
+ cur_dev->path = (char*) calloc(len+1, sizeof(char));
+ strncpy(cur_dev->path, str, len+1);
+ cur_dev->path[len] = '\0';
+ }
+ else
+ cur_dev->path = NULL;
+
+ /* Serial Number */
+ wstr[0]= 0x0000;
+ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));
+ wstr[WSTR_LEN-1] = 0x0000;
+ if (res) {
+ cur_dev->serial_number = _wcsdup(wstr);
+ }
+
+ /* Manufacturer String */
+ wstr[0]= 0x0000;
+ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));
+ wstr[WSTR_LEN-1] = 0x0000;
+ if (res) {
+ cur_dev->manufacturer_string = _wcsdup(wstr);
+ }
+
+ /* Product String */
+ wstr[0]= 0x0000;
+ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));
+ wstr[WSTR_LEN-1] = 0x0000;
+ if (res) {
+ cur_dev->product_string = _wcsdup(wstr);
+ }
+
+ /* VID/PID */
+ cur_dev->vendor_id = attrib.VendorID;
+ cur_dev->product_id = attrib.ProductID;
+
+ /* Release Number */
+ cur_dev->release_number = attrib.VersionNumber;
+
+ /* Interface Number. It can sometimes be parsed out of the path
+ on Windows if a device has multiple interfaces. See
+ http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
+ search for "Hardware IDs for HID Devices" at MSDN. If it's not
+ in the path, it's set to -1. */
+ cur_dev->interface_number = -1;
+ if (cur_dev->path) {
+ char *interface_component = strstr(cur_dev->path, "&mi_");
+ if (interface_component) {
+ char *hex_str = interface_component + 4;
+ char *endptr = NULL;
+ cur_dev->interface_number = strtol(hex_str, &endptr, 16);
+ if (endptr == hex_str) {
+ /* The parsing failed. Set interface_number to -1. */
+ cur_dev->interface_number = -1;
+ }
+ }
+ }
+ }
+
+cont_close:
+ CloseHandle(write_handle);
+cont:
+ /* We no longer need the detail data. It can be freed */
+ free(device_interface_detail_data);
+
+ device_index++;
+
+ }
+
+ /* Close the device information handle. */
+ SetupDiDestroyDeviceInfoList(device_info_set);
+
+ return root;
+
+}
+
+void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
+{
+ /* TODO: Merge this with the Linux version. This function is platform-independent. */
+ struct hid_device_info *d = devs;
+ while (d) {
+ struct hid_device_info *next = d->next;
+ free(d->path);
+ free(d->serial_number);
+ free(d->manufacturer_string);
+ free(d->product_string);
+ free(d);
+ d = next;
+ }
+}
+
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
+{
+ /* TODO: Merge this functions with the Linux version. This function should be platform independent. */
+ struct hid_device_info *devs, *cur_dev;
+ const char *path_to_open = NULL;
+ hid_device *handle = NULL;
+
+ devs = hid_enumerate(vendor_id, product_id);
+ cur_dev = devs;
+ while (cur_dev) {
+ if (cur_dev->vendor_id == vendor_id &&
+ cur_dev->product_id == product_id) {
+ if (serial_number) {
+ if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ else {
+ path_to_open = cur_dev->path;
+ break;
+ }
+ }
+ cur_dev = cur_dev->next;
+ }
+
+ if (path_to_open) {
+ /* Open the device */
+ handle = hid_open_path(path_to_open);
+ }
+
+ hid_free_enumeration(devs);
+
+ return handle;
+}
+
+HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
+{
+ hid_device *dev;
+ HIDP_CAPS caps;
+ PHIDP_PREPARSED_DATA pp_data = NULL;
+ BOOLEAN res;
+ NTSTATUS nt_res;
+
+ if (hid_init() < 0) {
+ return NULL;
+ }
+
+ dev = new_hid_device();
+
+ /* Open a handle to the device */
+ dev->device_handle = open_device(path, TRUE);
+
+ /* Check validity of write_handle. */
+ if (dev->device_handle == INVALID_HANDLE_VALUE) {
+ /* System devices, such as keyboards and mice, cannot be opened in
+ read-write mode, because the system takes exclusive control over
+ them. This is to prevent keyloggers. However, feature reports
+ can still be sent and received. Retry opening the device, but
+ without read/write access. */
+ dev->device_handle = open_device(path, FALSE);
+
+ /* Check the validity of the limited device_handle. */
+ if (dev->device_handle == INVALID_HANDLE_VALUE) {
+ /* Unable to open the device, even without read-write mode. */
+ register_error(dev, "CreateFile");
+ goto err;
+ }
+ }
+
+ /* Set the Input Report buffer size to 64 reports. */
+ res = HidD_SetNumInputBuffers(dev->device_handle, 64);
+ if (!res) {
+ register_error(dev, "HidD_SetNumInputBuffers");
+ goto err;
+ }
+
+ /* Get the Input Report length for the device. */
+ res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
+ if (!res) {
+ register_error(dev, "HidD_GetPreparsedData");
+ goto err;
+ }
+ nt_res = HidP_GetCaps(pp_data, &caps);
+ if (nt_res != HIDP_STATUS_SUCCESS) {
+ register_error(dev, "HidP_GetCaps");
+ goto err_pp_data;
+ }
+ dev->output_report_length = caps.OutputReportByteLength;
+ dev->input_report_length = caps.InputReportByteLength;
+ HidD_FreePreparsedData(pp_data);
+
+ dev->read_buf = (char*) malloc(dev->input_report_length);
+
+ return dev;
+
+err_pp_data:
+ HidD_FreePreparsedData(pp_data);
+err:
+ free_hid_device(dev);
+ return NULL;
+}
+
+int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+ DWORD bytes_written;
+ BOOL res;
+
+ OVERLAPPED ol;
+ unsigned char *buf;
+ memset(&ol, 0, sizeof(ol));
+
+ /* Make sure the right number of bytes are passed to WriteFile. Windows
+ expects the number of bytes which are in the _longest_ report (plus
+ one for the report number) bytes even if the data is a report
+ which is shorter than that. Windows gives us this value in
+ caps.OutputReportByteLength. If a user passes in fewer bytes than this,
+ create a temporary buffer which is the proper size. */
+ if (length >= dev->output_report_length) {
+ /* The user passed the right number of bytes. Use the buffer as-is. */
+ buf = (unsigned char *) data;
+ } else {
+ /* Create a temporary buffer and copy the user's data
+ into it, padding the rest with zeros. */
+ buf = (unsigned char *) malloc(dev->output_report_length);
+ memcpy(buf, data, length);
+ memset(buf + length, 0, dev->output_report_length - length);
+ length = dev->output_report_length;
+ }
+
+ res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
+
+ if (!res) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ /* WriteFile() failed. Return error. */
+ register_error(dev, "WriteFile");
+ bytes_written = -1;
+ goto end_of_function;
+ }
+ }
+
+ /* Wait here until the write is done. This makes
+ hid_write() synchronous. */
+ res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
+ if (!res) {
+ /* The Write operation failed. */
+ register_error(dev, "WriteFile");
+ bytes_written = -1;
+ goto end_of_function;
+ }
+
+end_of_function:
+ if (buf != data)
+ free(buf);
+
+ return bytes_written;
+}
+
+
+int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+ DWORD bytes_read = 0;
+ size_t copy_len = 0;
+ BOOL res;
+
+ /* Copy the handle for convenience. */
+ HANDLE ev = dev->ol.hEvent;
+
+ if (!dev->read_pending) {
+ /* Start an Overlapped I/O read. */
+ dev->read_pending = TRUE;
+ memset(dev->read_buf, 0, dev->input_report_length);
+ ResetEvent(ev);
+ res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
+
+ if (!res) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ /* ReadFile() has failed.
+ Clean up and return error. */
+ CancelIo(dev->device_handle);
+ dev->read_pending = FALSE;
+ goto end_of_function;
+ }
+ }
+ }
+
+ if (milliseconds >= 0) {
+ /* See if there is any data yet. */
+ res = WaitForSingleObject(ev, milliseconds);
+ if (res != WAIT_OBJECT_0) {
+ /* There was no data this time. Return zero bytes available,
+ but leave the Overlapped I/O running. */
+ return 0;
+ }
+ }
+
+ /* Either WaitForSingleObject() told us that ReadFile has completed, or
+ we are in non-blocking mode. Get the number of bytes read. The actual
+ data has been copied to the data[] array which was passed to ReadFile(). */
+ res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
+
+ /* Set pending back to false, even if GetOverlappedResult() returned error. */
+ dev->read_pending = FALSE;
+
+ if (res && bytes_read > 0) {
+ if (dev->read_buf[0] == 0x0) {
+ /* If report numbers aren't being used, but Windows sticks a report
+ number (0x0) on the beginning of the report anyway. To make this
+ work like the other platforms, and to make it work more like the
+ HID spec, we'll skip over this byte. */
+ bytes_read--;
+ copy_len = length > bytes_read ? bytes_read : length;
+ memcpy(data, dev->read_buf+1, copy_len);
+ }
+ else {
+ /* Copy the whole buffer, report number and all. */
+ copy_len = length > bytes_read ? bytes_read : length;
+ memcpy(data, dev->read_buf, copy_len);
+ }
+ }
+
+end_of_function:
+ if (!res) {
+ register_error(dev, "GetOverlappedResult");
+ return -1;
+ }
+
+ return copy_len;
+}
+
+int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+ return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
+}
+
+int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+ dev->blocking = !nonblock;
+ return 0; /* Success */
+}
+
+int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+ BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length);
+ if (!res) {
+ register_error(dev, "HidD_SetFeature");
+ return -1;
+ }
+
+ return length;
+}
+
+
+int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ BOOL res;
+#if 0
+ res = HidD_GetFeature(dev->device_handle, data, length);
+ if (!res) {
+ register_error(dev, "HidD_GetFeature");
+ return -1;
+ }
+ return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
+#else
+ DWORD bytes_returned;
+
+ OVERLAPPED ol;
+ memset(&ol, 0, sizeof(ol));
+
+ res = DeviceIoControl(dev->device_handle,
+ IOCTL_HID_GET_FEATURE,
+ data, length,
+ data, length,
+ &bytes_returned, &ol);
+
+ if (!res) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ /* DeviceIoControl() failed. Return error. */
+ register_error(dev, "Send Feature Report DeviceIoControl");
+ return -1;
+ }
+ }
+
+ /* Wait here until the write is done. This makes
+ hid_get_feature_report() synchronous. */
+ res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
+ if (!res) {
+ /* The operation failed. */
+ register_error(dev, "Send Feature Report GetOverLappedResult");
+ return -1;
+ }
+
+ /* bytes_returned does not include the first byte which contains the
+ report ID. The data buffer actually contains one more byte than
+ bytes_returned. */
+ bytes_returned++;
+
+ return bytes_returned;
+#endif
+}
+
+
+int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ BOOL res;
+#if 0
+ res = HidD_GetInputReport(dev->device_handle, data, length);
+ if (!res) {
+ register_error(dev, "HidD_GetInputReport");
+ return -1;
+ }
+ return length;
+#else
+ DWORD bytes_returned;
+
+ OVERLAPPED ol;
+ memset(&ol, 0, sizeof(ol));
+
+ res = DeviceIoControl(dev->device_handle,
+ IOCTL_HID_GET_INPUT_REPORT,
+ data, length,
+ data, length,
+ &bytes_returned, &ol);
+
+ if (!res) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ /* DeviceIoControl() failed. Return error. */
+ register_error(dev, "Send Input Report DeviceIoControl");
+ return -1;
+ }
+ }
+
+ /* Wait here until the write is done. This makes
+ hid_get_feature_report() synchronous. */
+ res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
+ if (!res) {
+ /* The operation failed. */
+ register_error(dev, "Send Input Report GetOverLappedResult");
+ return -1;
+ }
+
+ /* bytes_returned does not include the first byte which contains the
+ report ID. The data buffer actually contains one more byte than
+ bytes_returned. */
+ bytes_returned++;
+
+ return bytes_returned;
+#endif
+}
+
+void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
+{
+ if (!dev)
+ return;
+ CancelIo(dev->device_handle);
+ free_hid_device(dev);
+}
+
+int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ BOOL res;
+
+ res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
+ if (!res) {
+ register_error(dev, "HidD_GetManufacturerString");
+ return -1;
+ }
+
+ return 0;
+}
+
+int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ BOOL res;
+
+ res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
+ if (!res) {
+ register_error(dev, "HidD_GetProductString");
+ return -1;
+ }
+
+ return 0;
+}
+
+int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ BOOL res;
+
+ res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
+ if (!res) {
+ register_error(dev, "HidD_GetSerialNumberString");
+ return -1;
+ }
+
+ return 0;
+}
+
+int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+ BOOL res;
+
+ res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * MIN(maxlen, MAX_STRING_WCHARS));
+ if (!res) {
+ register_error(dev, "HidD_GetIndexedString");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
+{
+ if (dev) {
+ if (dev->last_error_str == NULL)
+ return L"Success";
+ return (wchar_t*)dev->last_error_str;
+ }
+
+ // Global error messages are not (yet) implemented on Windows.
+ return L"hid_error for global errors is not implemented yet";
+}
+
+
+/*#define PICPGM*/
+/*#define S11*/
+#define P32
+#ifdef S11
+ unsigned short VendorID = 0xa0a0;
+ unsigned short ProductID = 0x0001;
+#endif
+
+#ifdef P32
+ unsigned short VendorID = 0x04d8;
+ unsigned short ProductID = 0x3f;
+#endif
+
+
+#ifdef PICPGM
+ unsigned short VendorID = 0x04d8;
+ unsigned short ProductID = 0x0033;
+#endif
+
+
+#if 0
+int __cdecl main(int argc, char* argv[])
+{
+ int res;
+ unsigned char buf[65];
+
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ /* Set up the command buffer. */
+ memset(buf,0x00,sizeof(buf));
+ buf[0] = 0;
+ buf[1] = 0x81;
+
+
+ /* Open the device. */
+ int handle = open(VendorID, ProductID, L"12345");
+ if (handle < 0)
+ printf("unable to open device\n");
+
+
+ /* Toggle LED (cmd 0x80) */
+ buf[1] = 0x80;
+ res = write(handle, buf, 65);
+ if (res < 0)
+ printf("Unable to write()\n");
+
+ /* Request state (cmd 0x81) */
+ buf[1] = 0x81;
+ write(handle, buf, 65);
+ if (res < 0)
+ printf("Unable to write() (2)\n");
+
+ /* Read requested state */
+ read(handle, buf, 65);
+ if (res < 0)
+ printf("Unable to read()\n");
+
+ /* Print out the returned buffer. */
+ for (int i = 0; i < 4; i++)
+ printf("buf[%d]: %d\n", i, buf[i]);
+
+ return 0;
+}
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
diff --git a/c/src/third-party/hidapi/windows/hidapi.sln b/c/src/third-party/hidapi/windows/hidapi.sln
new file mode 100644
index 000000000..aeb2660e6
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hidapi.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.136
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcxproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.Build.0 = Debug|Win32
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.ActiveCfg = Debug|x64
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.ActiveCfg = Release|Win32
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.Build.0 = Release|Win32
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.ActiveCfg = Debug|Win32
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.Build.0 = Debug|Win32
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.ActiveCfg = Debug|x64
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.Build.0 = Debug|x64
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.ActiveCfg = Release|Win32
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.Build.0 = Release|Win32
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.ActiveCfg = Release|x64
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {8749E535-9C65-4A89-840E-78D7578C7866}
+ EndGlobalSection
+EndGlobal
diff --git a/c/src/third-party/hidapi/windows/hidapi.vcproj b/c/src/third-party/hidapi/windows/hidapi.vcproj
new file mode 100644
index 000000000..ee9569c7d
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hidapi.vcproj
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/third-party/hidapi/windows/hidapi.vcxproj b/c/src/third-party/hidapi/windows/hidapi.vcxproj
new file mode 100644
index 000000000..c793017bf
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hidapi.vcxproj
@@ -0,0 +1,160 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {A107C21C-418A-4697-BB10-20C3AA60E2E4}
+ hidapi
+ Win32Proj
+
+
+
+ DynamicLibrary
+ v140
+ Unicode
+ true
+
+
+ DynamicLibrary
+ v140
+ Unicode
+ true
+
+
+ DynamicLibrary
+ v140
+ Unicode
+
+
+ DynamicLibrary
+ v140
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>14.0.25431.1
+
+
+
+
+
+
+
+ Disabled
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+ Level3
+ EditAndContinue
+
+
+ setupapi.lib;%(AdditionalDependencies)
+ true
+ Windows
+ MachineX86
+
+
+
+
+ Disabled
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+
+ Level3
+ EditAndContinue
+
+
+ setupapi.lib;%(AdditionalDependencies)
+ true
+ Windows
+
+
+
+
+ MaxSpeed
+ true
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreaded
+ true
+
+ Level3
+ ProgramDatabase
+
+
+ setupapi.lib;%(AdditionalDependencies)
+ true
+ Windows
+ true
+ true
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;HIDAPI_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreaded
+ true
+
+
+ Level3
+ ProgramDatabase
+
+
+ setupapi.lib;%(AdditionalDependencies)
+ true
+ Windows
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/third-party/hidapi/windows/hidtest.vcproj b/c/src/third-party/hidapi/windows/hidtest.vcproj
new file mode 100644
index 000000000..abee0eb2b
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hidtest.vcproj
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/third-party/hidapi/windows/hidtest.vcxproj b/c/src/third-party/hidapi/windows/hidtest.vcxproj
new file mode 100644
index 000000000..b3d8fbc1d
--- /dev/null
+++ b/c/src/third-party/hidapi/windows/hidtest.vcxproj
@@ -0,0 +1,156 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {23E9FF6A-49D1-4993-B2B5-BBB992C6C712}
+ hidtest
+
+
+
+ Application
+ v140
+ MultiByte
+ true
+
+
+ Application
+ v140
+ MultiByte
+ true
+
+
+ Application
+ v140
+ MultiByte
+
+
+ Application
+ v140
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>14.0.25431.1
+
+
+
+
+
+
+
+ Disabled
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Level3
+ EditAndContinue
+
+
+ hidapi.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ Console
+ MachineX86
+
+
+
+
+ Disabled
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Level3
+ EditAndContinue
+
+
+ hidapi.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ Console
+
+
+
+
+ MaxSpeed
+ true
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ true
+ Level3
+ ProgramDatabase
+
+
+ hidapi.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ Console
+ true
+ true
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ ..\hidapi;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ true
+ Level3
+ ProgramDatabase
+
+
+ hidapi.lib;%(AdditionalDependencies)
+ $(SolutionDir)$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)
+ true
+ Console
+ true
+ true
+
+
+
+
+
+
+
+ {a107c21c-418a-4697-bb10-20c3aa60e2e4}
+ false
+
+
+
+
+
+
diff --git a/c/src/third-party/libscrypt/Makefile b/c/src/third-party/libscrypt/Makefile
index bb37d24a2..0e09dfc5d 100644
--- a/c/src/third-party/libscrypt/Makefile
+++ b/c/src/third-party/libscrypt/Makefile
@@ -56,3 +56,4 @@ install-osx: libscrypt.so.0
install-static: libscrypt.a
$(INSTALL_DATA) -pm 0644 libscrypt.a $(DESTDIR)$(LIBDIR)
+
diff --git a/c/src/transport/curl/in3_curl.c b/c/src/transport/curl/in3_curl.c
index a832bdd8d..1f728c4d1 100644
--- a/c/src/transport/curl/in3_curl.c
+++ b/c/src/transport/curl/in3_curl.c
@@ -75,7 +75,7 @@ static void readDataNonBlocking(CURLM* cm, const char* url, const char* payload,
res = curl_multi_add_handle(cm, curl);
if (res != CURLM_OK) {
sb_add_chars(&r->error, "curl_multi_add_handle() failed:");
- sb_add_chars(&r->error, (char*) curl_easy_strerror(res));
+ sb_add_chars(&r->error, (char*) curl_easy_strerror((CURLcode) res));
}
} else
sb_add_chars(&r->error, "no curl:");
diff --git a/c/src/verifier/btc/btc_serialize.c b/c/src/verifier/btc/btc_serialize.c
index 22f32873b..650c5e846 100644
--- a/c/src/verifier/btc/btc_serialize.c
+++ b/c/src/verifier/btc/btc_serialize.c
@@ -31,6 +31,7 @@ bytes_t btc_block_get(bytes_t block, btc_block_field field) {
case BTC_B_BITS: return bytes(block.data + 72, 4);
case BTC_B_NONCE: return bytes(block.data + 76, 4);
case BTC_B_HEADER: return bytes(block.data, 80);
+ default: return bytes(NULL, 0);
}
}
void btc_hash(bytes_t data, bytes32_t dst) {
diff --git a/c/src/verifier/eth1/basic/CMakeLists.txt b/c/src/verifier/eth1/basic/CMakeLists.txt
index 3967961c1..2be7564a4 100644
--- a/c/src/verifier/eth1/basic/CMakeLists.txt
+++ b/c/src/verifier/eth1/basic/CMakeLists.txt
@@ -48,4 +48,9 @@ add_library(eth_basic_o OBJECT
# add dependency
add_library(eth_basic STATIC $)
-target_link_libraries(eth_basic eth_nano)
+
+if( LEDGER_NANO AND HIDAPI)
+ target_link_libraries(eth_basic eth_nano ledger_signer)
+else()
+ target_link_libraries(eth_basic eth_nano )
+endif()
\ No newline at end of file
diff --git a/c/src/verifier/eth1/basic/signer.c b/c/src/verifier/eth1/basic/signer.c
index ee2263679..fc51a7834 100644
--- a/c/src/verifier/eth1/basic/signer.c
+++ b/c/src/verifier/eth1/basic/signer.c
@@ -35,6 +35,11 @@
#include "../../../core/client/client.h"
#include "../../../core/client/keys.h"
#include "../../../core/util/mem.h"
+
+#if defined(LEDGER_NANO)
+#include "../../../signer/ledger-nano/signer/ledger_signer.h"
+#endif
+
#include "../../../third-party/crypto/ecdsa.h"
#include "../../../third-party/crypto/secp256k1.h"
#include "../../../verifier/eth1/nano/serialize.h"
@@ -121,6 +126,20 @@ in3_ret_t eth_set_pk_signer(in3_t* in3, bytes32_t pk) {
return IN3_OK;
}
+/** sets the signer and a pk to the client*/
+uint8_t* eth_set_pk_signer_hex(in3_t* in3, char* key) {
+ if (key[0] == '0' && key[1] == 'x') key += 2;
+ if (strlen(key) != 64) return NULL;
+ uint8_t* key_bytes = _malloc(32);
+ hex_to_bytes(key, 64, key_bytes, 32);
+ in3_ret_t res = eth_set_pk_signer(in3, key_bytes);
+ if (res) {
+ _free(key_bytes);
+ return NULL;
+ }
+ return key_bytes;
+}
+
bytes_t sign_tx(d_token_t* tx, in3_ctx_t* ctx) {
address_t from;
bytes_t tmp;
@@ -144,7 +163,11 @@ bytes_t sign_tx(d_token_t* tx, in3_ctx_t* ctx) {
// Note: This works because the signer->wallet points to the pk in the current signer implementation
// (see eth_set_pk_signer()), and may change in the future.
// Also, other wallet implementations may differ - hence the check.
+#if defined(LEDGER_NANO)
+ if (!ctx->client->signer || (ctx->client->signer->sign != eth_sign && ctx->client->signer->sign != eth_ledger_sign)) {
+#else
if (!ctx->client->signer || ctx->client->signer->sign != eth_sign) {
+#endif
if (new_json) json_free(new_json);
ctx_set_error(ctx, "you need to specify the from-address in the tx!", IN3_EINVAL);
return bytes(NULL, 0);
@@ -152,7 +175,19 @@ bytes_t sign_tx(d_token_t* tx, in3_ctx_t* ctx) {
uint8_t public_key[65], sdata[32];
bytes_t pubkey_bytes = {.data = public_key + 1, .len = 64};
+
+#if defined(LEDGER_NANO)
+ if (ctx->client->signer->sign == eth_ledger_sign) {
+ uint8_t bip32[32];
+ memcpy(bip32, ctx->client->signer->wallet, 5);
+ eth_ledger_get_public_key(bip32, public_key);
+
+ } else {
+ ecdsa_get_public_key65(&secp256k1, ctx->client->signer->wallet, public_key);
+ }
+#else
ecdsa_get_public_key65(&secp256k1, ctx->client->signer->wallet, public_key);
+#endif
sha3_to(&pubkey_bytes, sdata);
memcpy(from, sdata + 12, 20);
} else
diff --git a/c/src/verifier/eth1/basic/signer.h b/c/src/verifier/eth1/basic/signer.h
index 4854f8eb4..90cf6cbe9 100644
--- a/c/src/verifier/eth1/basic/signer.h
+++ b/c/src/verifier/eth1/basic/signer.h
@@ -49,4 +49,9 @@
*/
in3_ret_t eth_set_pk_signer(in3_t* in3, bytes32_t pk);
+/**
+ * simply signer with one private key as hex.
+ */
+uint8_t* eth_set_pk_signer_hex(in3_t* in3, char* key);
+
#endif
diff --git a/c/src/verifier/eth1/rpc/rpc.c b/c/src/verifier/eth1/rpc/rpc.c
index 629a8042b..26dfa7c7b 100644
--- a/c/src/verifier/eth1/rpc/rpc.c
+++ b/c/src/verifier/eth1/rpc/rpc.c
@@ -10,10 +10,12 @@
static verify_res_t report(char* msg, d_token_t* value, char* prefix) {
char* m = malloc(strlen(msg) + (prefix ? (strlen(prefix) + 1) : 0) + 1);
- if (prefix)
- sprintf(m, "%s %s", prefix, msg);
- else
- memcpy(m, msg, strlen(msg) + 1);
+ if (m) {
+ if (prefix)
+ sprintf(m, "%s %s", prefix, msg);
+ else
+ memcpy(m, msg, strlen(msg) + 1);
+ }
verify_res_t r = {.src = value ? d_create_json(value) : NULL, .msg = m, .valid = false};
return r;
}
diff --git a/code-quality.gitlab-ci.yml b/code-quality.gitlab-ci.yml
new file mode 100644
index 000000000..7cae68db2
--- /dev/null
+++ b/code-quality.gitlab-ci.yml
@@ -0,0 +1,32 @@
+# Copied from gitlab template, modified to remove the only/except
+code_quality:
+ stage: test
+ image: docker:19.03.8
+ allow_failure: true
+ services:
+ - docker:19.03.8-dind
+ variables:
+ DOCKER_DRIVER: overlay2
+ DOCKER_TLS_CERTDIR: ""
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.9"
+ script:
+ - |
+ if ! docker info &>/dev/null; then
+ if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
+ export DOCKER_HOST='tcp://localhost:2375'
+ fi
+ fi
+ - docker pull --quiet "$CODE_QUALITY_IMAGE"
+ - docker run
+ --env SOURCE_CODE="$PWD"
+ --volume "$PWD":/code
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "$CODE_QUALITY_IMAGE" /code
+ artifacts:
+ reports:
+ codequality: gl-code-quality-report.json
+ expire_in: 1 week
+ dependencies: []
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]*\.[0-9]*\.[0-9]*-?.*$/'
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
diff --git a/dotnet/ConsoleTest/ConsoleTest.csproj b/dotnet/ConsoleTest/ConsoleTest.csproj
index 5a9435d1b..5e847af8f 100644
--- a/dotnet/ConsoleTest/ConsoleTest.csproj
+++ b/dotnet/ConsoleTest/ConsoleTest.csproj
@@ -9,4 +9,6 @@
+
+
diff --git a/dotnet/In3/BlockParameter.cs b/dotnet/In3/BlockParameter.cs
index 24b70f731..c8f418263 100644
--- a/dotnet/In3/BlockParameter.cs
+++ b/dotnet/In3/BlockParameter.cs
@@ -11,5 +11,11 @@ public static BigInteger Latest {
public static BigInteger Earliest {
get { return 0; }
}
+ public static string AsString(BigInteger block)
+ {
+ if (block == Latest) return "latest";
+ if (block == Earliest || block < -1) return "earliest";
+ return TypesMatcher.BigIntToPrefixedHex(block);
+ }
}
}
\ No newline at end of file
diff --git a/dotnet/In3/Configuration/BaseConfiguration.cs b/dotnet/In3/Configuration/BaseConfiguration.cs
new file mode 100644
index 000000000..3b15eb201
--- /dev/null
+++ b/dotnet/In3/Configuration/BaseConfiguration.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace In3.Configuration
+{
+ public abstract class BaseConfiguration
+ {
+ // Consider using composite pattern
+ private readonly Dictionary _state;
+ private bool _isDirty;
+
+ public BaseConfiguration()
+ {
+ _state = new Dictionary();
+ }
+
+ public abstract bool HasChanged();
+
+ protected object GetState(string key)
+ {
+ return _state.ContainsKey(key) ?_state[key] : null;
+ }
+
+ protected void SetState(string key, object value)
+ {
+ MarkAsDirty(!_state.ContainsKey(key) || _state[key] != value);
+ _state[key] = value;
+ }
+
+ protected bool IsDirty()
+ {
+ return _isDirty;
+ }
+
+ internal void Clean()
+ {
+ _isDirty = false;
+ }
+
+ private void MarkAsDirty(bool becameDirty)
+ {
+ _isDirty = _isDirty || becameDirty;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Configuration/ChainConfiguration.cs b/dotnet/In3/Configuration/ChainConfiguration.cs
new file mode 100644
index 000000000..29a107226
--- /dev/null
+++ b/dotnet/In3/Configuration/ChainConfiguration.cs
@@ -0,0 +1,82 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Serialization;
+
+namespace In3.Configuration
+{
+ public class ChainConfiguration : BaseConfiguration
+ {
+ private List _nodesConfig { get; set; }
+
+ [JsonPropertyName("nodeList")]
+ public List NodesConfiguration
+ {
+ get => _nodesConfig;
+ }
+ [JsonPropertyName("needsUpdate")]
+ public bool? NeedsUpdate
+ {
+ get => (bool?)GetState("needsUpdate");
+ set => SetState("needsUpdate", value);
+ }
+ [JsonPropertyName("contract")]
+ public string? Contract
+ {
+ get => (string?)GetState("contract");
+ set => SetState("contract", value);
+ }
+ [JsonPropertyName("registryId")]
+ public string RegistryId
+ {
+ get => (string?)GetState("registryId");
+ set => SetState("registryId", value);
+ }
+ [JsonPropertyName("whiteListContract")]
+ public string WhiteListContract
+ {
+ get => (string?)GetState("whiteListContract");
+ set => SetState("whiteListContract", value);
+ }
+ [JsonPropertyName("whiteList")]
+ public string[] WhiteList
+ {
+ get => (string[]) GetState("whiteList");
+ set => SetState("whiteList", value);
+ }
+
+
+ internal ChainConfiguration() {}
+
+ public ChainConfiguration(Chain chain, ClientConfiguration clientConfiguration)
+ {
+ clientConfiguration.AddChainConfiguration(chain, this);
+ }
+
+ public void AddNodeConfiguration(NodeConfiguration nodeConfiguration)
+ {
+ if (_nodesConfig == null)
+ {
+ _nodesConfig = new List();
+ }
+ _nodesConfig.Add(nodeConfiguration);
+ }
+
+ public override bool HasChanged()
+ {
+ bool hasChildrenChanged = NodesConfiguration != null && NodesConfiguration.Any(configuration => configuration.HasChanged());
+ return IsDirty() || hasChildrenChanged;
+ }
+
+ internal void MarkSynced()
+ {
+ Clean();
+ if (NodesConfiguration != null)
+ {
+ foreach (var nodeConfiguration in NodesConfiguration)
+ {
+ nodeConfiguration.MarkSynced();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Configuration/ClientConfiguration.cs b/dotnet/In3/Configuration/ClientConfiguration.cs
new file mode 100644
index 000000000..c6fb4af7a
--- /dev/null
+++ b/dotnet/In3/Configuration/ClientConfiguration.cs
@@ -0,0 +1,173 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using SystemTextJsonSamples;
+using csharp.Utils;
+
+namespace In3.Configuration
+{
+ public class ClientConfiguration : BaseConfiguration
+ {
+ [JsonPropertyName("nodes"), JsonConverter(typeof(DictionaryChainObjectConverter))]
+ public Dictionary ChainsConfiguration { get; set; }
+ [JsonPropertyName("requestCount")]
+ public uint RequestCount
+ {
+ get => (uint)GetState("requestCount");
+ set => SetState("requestCount", value);
+ }
+ [JsonPropertyName("autoUpdateList")]
+ public bool AutoUpdateList
+ {
+ get => (bool)GetState("autoUpdateList");
+ set => SetState("autoUpdateList", value);
+ }
+ [JsonPropertyName("proof"), JsonConverter(typeof(ProofConverter))]
+ public Proof Proof
+ {
+ get => (Proof)GetState("proof");
+ set => SetState("proof", value);
+ }
+ [JsonPropertyName("maxAttempts")]
+ public uint MaxAttempts
+ {
+ get => (uint)GetState("maxAttempts");
+ set => SetState("maxAttempts", value);
+ }
+ [JsonPropertyName("signatureCount")]
+ public uint SignatureCount
+ {
+ get => (uint)GetState("signatureCount");
+ set => SetState("signatureCount", value);
+ }
+ [JsonPropertyName("finality")]
+ public uint Finality
+ {
+ get => (uint)GetState("finality");
+ set => SetState("finality", value);
+ }
+ [JsonPropertyName("includeCode")]
+ public bool IncludeCode
+ {
+ get => (bool)GetState("includeCode");
+ set => SetState("includeCode", value);
+ }
+ [JsonPropertyName("keepIn3")]
+ public bool KeepIn3
+ {
+ get => (bool)GetState("keepIn3");
+ set => SetState("keepIn3", value);
+ }
+ [JsonPropertyName("useBinary")]
+ public bool UseBinary
+ {
+ get => (bool)GetState("useBinary");
+ set => SetState("useBinary", value);
+ }
+ [JsonPropertyName("useHttp")]
+ public bool UseHttp
+ {
+ get => (bool)GetState("useHttp");
+ set => SetState("useHttp", value);
+ }
+ [JsonPropertyName("maxCodeCache")]
+ public ulong MaxCodeCache
+ {
+ get => (ulong)GetState("maxCodeCache");
+ set => SetState("maxCodeCache", value);
+ }
+ [JsonPropertyName("timeout")]
+ public ulong Timeout
+ {
+ get => (ulong)GetState("timeout");
+ set => SetState("timeout", value);
+ }
+ [JsonPropertyName("minDeposit")]
+ public ulong MinDeposit
+ {
+ get => (ulong)GetState("minDeposit");
+ set => SetState("minDeposit", value);
+ }
+ [JsonPropertyName("nodeProps")]
+ public ulong NodeProps
+ {
+ get => (ulong)GetState("nodeProps");
+ set => SetState("nodeProps", value);
+ }
+ [JsonPropertyName("nodeLimit")]
+ public ulong NodeLimit
+ {
+ get => (ulong)GetState("nodeLimit");
+ set => SetState("nodeLimit", value);
+ }
+ [JsonPropertyName("replaceLatestBlock")]
+ public uint? ReplaceLatestBlock
+ {
+ get => (uint?)GetState("replaceLatestBlock");
+ set => SetState("replaceLatestBlock", value);
+ }
+ [JsonPropertyName("maxBlockCache")]
+ public ulong MaxBlockCache
+ {
+ get => (ulong)GetState("maxBlockCache");
+ set => SetState("maxBlockCache", value);
+ }
+ [JsonPropertyName("rpc")]
+ public string? Rpc
+ {
+ get => (string?)GetState("rpc");
+ set => SetState("rpc", value);
+ }
+ [JsonPropertyName("stats")]
+ public bool Stats
+ {
+ get => (bool)GetState("stats");
+ set => SetState("stats", value);
+ }
+
+ public ClientConfiguration()
+ {
+ ChainsConfiguration = new Dictionary();
+ }
+
+ public string ToJson()
+ {
+ JsonSerializerOptions options = new JsonSerializerOptions
+ {
+ IgnoreNullValues = true
+ };
+
+ options.Converters.Add(new DictionaryChainObjectConverter());
+ options.Converters.Add(new ProofConverter());
+ return JsonSerializer.Serialize(this, options);
+ }
+
+ public override bool HasChanged()
+ {
+ bool hasChildrenChanged = ChainsConfiguration.Values.Any(configuration => configuration.HasChanged());
+ return IsDirty() || hasChildrenChanged;
+ }
+
+ internal void AddChainConfiguration(Chain chain, ChainConfiguration conf)
+ {
+ if (ChainsConfiguration.ContainsKey(chain))
+ {
+ ChainsConfiguration[chain] = conf;
+ }
+ else
+ {
+ ChainsConfiguration.Add(chain, conf);
+ }
+ }
+
+ internal void MarkSynced()
+ {
+ Clean();
+ foreach (var chainConfiguration in ChainsConfiguration.Values)
+ {
+ chainConfiguration.MarkSynced();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Configuration/NodeConfiguration.cs b/dotnet/In3/Configuration/NodeConfiguration.cs
new file mode 100644
index 000000000..dab040545
--- /dev/null
+++ b/dotnet/In3/Configuration/NodeConfiguration.cs
@@ -0,0 +1,35 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Configuration
+{
+ public class NodeConfiguration : BaseConfiguration
+ {
+ [JsonPropertyName("url")] public string Url {
+ get => (string) GetState("url");
+ set => SetState("url", value);
+ }
+ [JsonPropertyName("props")] public long? Props {
+ get => (long) GetState("props");
+ set => SetState("props", value);
+ }
+ [JsonPropertyName("address")] public string Address {
+ get => (string) GetState("address");
+ set => SetState("address", value);
+ }
+
+ public NodeConfiguration(ChainConfiguration config) {
+ config.AddNodeConfiguration(this);
+ }
+
+ public override bool HasChanged()
+ {
+ return IsDirty();
+ }
+
+ internal void MarkSynced()
+ {
+ Clean();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Configuration/Proof.cs b/dotnet/In3/Configuration/Proof.cs
new file mode 100644
index 000000000..5a872f144
--- /dev/null
+++ b/dotnet/In3/Configuration/Proof.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+
+namespace In3.Configuration
+{
+ public class Proof
+ {
+ private Proof(string value) { Value = value; }
+ private static Dictionary _valueToProof = new Dictionary {
+ {"none", None},
+ {"standard", Standard},
+ {"full", Full}
+ };
+
+ public static Proof FromValue(string value) => _valueToProof.ContainsKey(value) ? _valueToProof[value] : null;
+ public string Value { get; set; }
+
+ public static Proof None { get { return new Proof("none"); } }
+ public static Proof Standard { get { return new Proof("standard"); } }
+ public static Proof Full { get { return new Proof("full"); } }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/Account.cs b/dotnet/In3/Crypto/Account.cs
new file mode 100644
index 000000000..7635f9225
--- /dev/null
+++ b/dotnet/In3/Crypto/Account.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Crypto
+{
+ public class Account
+ {
+ [JsonPropertyName("address")] public string Address { get; set; }
+ [JsonPropertyName("publicKey")] public string PublicKey { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/Api.cs b/dotnet/In3/Crypto/Api.cs
new file mode 100644
index 000000000..c4a81bf6b
--- /dev/null
+++ b/dotnet/In3/Crypto/Api.cs
@@ -0,0 +1,60 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using In3.Utils;
+
+namespace In3.Crypto
+{
+ public class Api
+ {
+ private IN3 in3;
+
+ private const string CryptoPk2Address = "in3_pk2address";
+ private const string CryptoSignData = "in3_signData";
+ private static string CryptoPk2Public = "in3_pk2public";
+ private static string CryptoEcRecover = "in3_ecrecover";
+ private static string CryptoDecryptKey = "in3_decryptKey";
+ private static string CryptoSha3 = "web3_sha3";
+
+ public Api(IN3 client)
+ {
+ in3 = client;
+ }
+
+ public string Pk2Address(string key)
+ {
+ string jsonResponse = in3.SendRpc(CryptoPk2Address, new object[] { key });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public SignedData SignData(string msg, string key, SignatureType? sigType = null)
+ {
+ string jsonResponse = in3.SendRpc(CryptoSignData, new object[] { msg, key, sigType?.Value });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string Pk2Public(string key)
+ {
+ string jsonResponse = in3.SendRpc(CryptoPk2Public, new object[] { key });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Account EcRecover(string msg, string sig, SignatureType sigType)
+ {
+ string jsonResponse = in3.SendRpc(CryptoEcRecover, new object[] { msg, sig, sigType?.Value });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string DecryptKey(string key, string passphrase)
+ {
+ Dictionary res = JsonSerializer.Deserialize>(key);
+ string jsonResponse = in3.SendRpc(CryptoDecryptKey, new object[] { res, passphrase });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string Sha3(string data) {
+ string jsonResponse = in3.SendRpc(CryptoSha3, new object[] { data });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/SignatureType.cs b/dotnet/In3/Crypto/SignatureType.cs
new file mode 100644
index 000000000..936a65ea1
--- /dev/null
+++ b/dotnet/In3/Crypto/SignatureType.cs
@@ -0,0 +1,13 @@
+namespace In3.Crypto
+{
+ public class SignatureType
+ {
+ private SignatureType(string value) { Value = value; }
+
+ public string Value { get; set; }
+
+ public static SignatureType EthSign { get { return new SignatureType("eth_sign"); } }
+ public static SignatureType Raw { get { return new SignatureType("raw"); } }
+ public static SignatureType Hash { get { return new SignatureType("hash"); } }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/SignedData.cs b/dotnet/In3/Crypto/SignedData.cs
new file mode 100644
index 000000000..44ce6073e
--- /dev/null
+++ b/dotnet/In3/Crypto/SignedData.cs
@@ -0,0 +1,14 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Crypto
+{
+ public class SignedData
+ {
+ [JsonPropertyName("message")] public string Message { get; set; }
+ [JsonPropertyName("messageHash")] public string MessageHash { get; set; }
+ [JsonPropertyName("signature")] public string Signature { get; set; }
+ [JsonPropertyName("r")] public string R { get; set; }
+ [JsonPropertyName("s")] public string S { get; set; }
+ [JsonPropertyName("v")] public int V { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/Signer.cs b/dotnet/In3/Crypto/Signer.cs
new file mode 100644
index 000000000..29bc21e81
--- /dev/null
+++ b/dotnet/In3/Crypto/Signer.cs
@@ -0,0 +1,11 @@
+using In3.Eth1;
+
+namespace In3.Crypto
+{
+ public interface Signer
+ {
+ bool CanSign(string address);
+ string Sign(string data, string address);
+ public TransactionRequest PrepareTransaction(TransactionRequest tx);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Crypto/SimpleWallet.cs b/dotnet/In3/Crypto/SimpleWallet.cs
new file mode 100644
index 000000000..e623697f8
--- /dev/null
+++ b/dotnet/In3/Crypto/SimpleWallet.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using In3.Eth1;
+
+namespace In3.Crypto
+{
+ public class SimpleWallet : Signer
+ {
+ private Dictionary PrivateKeys { get; set; }
+ private IN3 In3 { get; set; }
+
+ public SimpleWallet(IN3 in3)
+ {
+ In3 = in3;
+ PrivateKeys = new Dictionary();
+ }
+
+ public string AddRawKey(string data) {
+ string address = GetAddress(data);
+ PrivateKeys.Add(address.ToLower(), data);
+ return address;
+ }
+
+ private string GetAddress(string key)
+ {
+ return In3.Crypto.Pk2Address(key);
+ }
+
+ private void SimpleSigner() {}
+
+ public bool CanSign(string address)
+ {
+ return PrivateKeys.ContainsKey(address);
+ }
+
+ public string Sign(string data, string address)
+ {
+ string key = PrivateKeys[address.ToLower()];
+ SignedData sign = In3.Crypto.SignData(data, key);
+ return sign.Signature;
+ }
+
+ public TransactionRequest PrepareTransaction(TransactionRequest tx)
+ {
+ return tx;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/API.cs b/dotnet/In3/Eth1/API.cs
deleted file mode 100644
index 469bb93fd..000000000
--- a/dotnet/In3/Eth1/API.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Numerics;
-using System.Text.Json;
-using In3.Rpc;
-using In3.Utils;
-
-namespace In3.Eth1
-{
- public class Api
- {
- private IN3 in3;
-
- private const string EthBlockNumber = "eth_blockNumber";
-
- public Api(IN3 in3)
- {
- this.in3 = in3;
- }
-
- public BigInteger BlockNumber()
- {
- string jsonResponse = in3.SendRPCasObject(EthBlockNumber, new object[] { });
- RpcResult response = JsonSerializer.Deserialize>(jsonResponse);
- return TypesMatcher.HexStringToBigint(response.Result);
- }
- }
-}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/Api.cs b/dotnet/In3/Eth1/Api.cs
new file mode 100644
index 000000000..c0d06456a
--- /dev/null
+++ b/dotnet/In3/Eth1/Api.cs
@@ -0,0 +1,329 @@
+using System;
+using System.Globalization;
+using System.Numerics;
+using System.Text.Json;
+using In3.Crypto;
+using In3.Rpc;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public class Api
+ {
+ private IN3 in3;
+
+ private const string EthBlockNumber = "eth_blockNumber";
+ private const string EthGetBlockByNumber = "eth_getBlockByNumber";
+ private const string EthGetBlockByHash = "eth_getBlockByHash";
+ private const string In3AbiEncode = "in3_abiEncode";
+ private const string In3AbiDecode = "in3_abiDecode";
+ private const string EthGasPrice = "eth_gasPrice";
+ private const string EthChainId = "eth_chainId";
+ private const string EthGetBalance = "eth_getBalance";
+ private const string EthGetCode = "eth_getCode";
+ private const string EthGetStorageAt = "eth_getStorageAt";
+ private const string EthGetBlockTransactionCountByHash = "eth_getBlockTransactionCountByHash";
+ private const string EthGetBlockTransactionCountByNumber = "eth_getBlockTransactionCountByNumber";
+ private const string EthGetTransactionByBlockHashAndIndex = "eth_getTransactionByBlockHashAndIndex";
+ private const string EthGetTransactionByBlockNumberAndIndex = "eth_getTransactionByBlockNumberAndIndex";
+ private const string EthGetTransactionByHash = "eth_getTransactionByHash";
+ private const string EthGetTransactionCount = "eth_getTransactionCount";
+ private const string EthSendRawTransaction = "eth_sendRawTransaction";
+ private const string EthSendTransaction = "eth_sendTransaction";
+ private const string EthChecksumAddress = "in3_checksumAddress";
+ private const string EthGetUncleCountByBlockHash = "eth_getUncleCountByBlockHash";
+ private const string EthGetUncleCountByBlockNumber = "eth_getUncleCountByBlockNumber";
+ private const string EthNewBlockFilter = "eth_newBlockFilter";
+ private const string EthUninstallFilter = "eth_uninstallFilter";
+ private const string EthCall = "eth_call";
+ private const string EthEstimateGas = "eth_estimateGas";
+ private const string EthNewFilter = "eth_newFilter";
+ private const string EthGetFilterChanges = "eth_getFilterChanges";
+ private const string EthGetFilterLogs = "eth_getFilterLogs";
+ private const string EthGetLogs = "eth_getLogs";
+ private const string EthGetTransactionReceipt = "eth_getTransactionReceipt";
+ private const string EthGetUncleByBlockNumberAndIndex = "eth_getUncleByBlockNumberAndIndex";
+ private const string EthENS = "in3_ens";
+
+ public Api(IN3 in3)
+ {
+ this.in3 = in3;
+ }
+
+ public BigInteger BlockNumber()
+ {
+ string jsonResponse = in3.SendRpc(EthBlockNumber, new object[] { });
+ return TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+
+ public Block GetBlockByNumber(BigInteger blockNumber, bool shouldIncludeTransactions = true)
+ {
+ string jsonResponse = in3.SendRpc(EthGetBlockByNumber,
+ new object[] { BlockParameter.AsString(blockNumber), true });
+ if (shouldIncludeTransactions)
+ {
+ return RpcHandler.From(jsonResponse);
+ }
+ else
+ {
+ return RpcHandler.From(jsonResponse);
+ }
+ }
+
+ public Block GetBlockByHash(string blockHash, bool shouldIncludeTransactions = true)
+ {
+ string jsonResponse = in3.SendRpc(EthGetBlockByHash,
+ new object[] { blockHash, shouldIncludeTransactions });
+ if (shouldIncludeTransactions)
+ {
+ return RpcHandler.From(jsonResponse);
+ }
+ else
+ {
+ return RpcHandler.From(jsonResponse);
+ }
+ }
+
+ public string AbiEncode(string signature, object[] args)
+ {
+ string jsonResponse = in3.SendRpc(In3AbiEncode, new object[] {
+ signature, args});
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string[] AbiDecode(string signature, string args)
+ {
+ string jsonResponse = in3.SendRpc(In3AbiDecode, new object[] {
+ signature, args});
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public BigInteger GetGasPrice()
+ {
+ string jsonResponse = in3.SendRpc(EthGasPrice, new object[] { });
+ return TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+ public Chain GetChainId()
+ {
+ string jsonResponse = in3.SendRpc(EthChainId, new object[] { });
+ return (Chain)(long)TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+
+ public BigInteger GetBalance(string address, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetBalance, new object[] { address, BlockParameter.AsString(block) });
+ return TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+
+ public string GetCode(string address, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetCode, new object[] { address, BlockParameter.AsString(block) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string GetStorageAt(string address, BigInteger position, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetStorageAt, new object[] {
+ address, TypesMatcher.BigIntToPrefixedHex(position), BlockParameter.AsString(block)
+ });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public long GetBlockTransactionCountByHash(string blockHash)
+ {
+ string jsonResponse = in3.SendRpc(EthGetBlockTransactionCountByHash, new object[] { blockHash });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public long GetBlockTransactionCountByNumber(BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetBlockTransactionCountByNumber, new object[] { BlockParameter.AsString(block) });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public Transaction GetTransactionByBlockHashAndIndex(String blockHash, int index)
+ {
+ string jsonResponse = in3.SendRpc(EthGetTransactionByBlockHashAndIndex,
+ new object[] { blockHash, BlockParameter.AsString(index) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Transaction GetTransactionByBlockNumberAndIndex(BigInteger block, int index)
+ {
+ string jsonResponse = in3.SendRpc(EthGetTransactionByBlockNumberAndIndex,
+ new object[] { BlockParameter.AsString(block), BlockParameter.AsString(index) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Transaction GetTransactionByHash(string transactionHash)
+ {
+ string jsonResponse = in3.SendRpc(EthGetTransactionByHash, new object[] { transactionHash });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public long GetTransactionCount(string address, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetTransactionCount, new object[] { address, BlockParameter.AsString(block) });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public string SendRawTransaction(string data)
+ {
+ string jsonResponse = in3.SendRpc(EthSendRawTransaction, new object[] { data });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string ChecksumAddress(string address, bool? shouldUseChainId = null)
+ {
+ string jsonResponse = in3.SendRpc(EthChecksumAddress, new object[] { address, shouldUseChainId });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public long GetUncleCountByBlockHash(string blockHash)
+ {
+ string jsonResponse = in3.SendRpc(EthGetUncleCountByBlockHash, new object[] { blockHash });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public long GetUncleCountByBlockNumber(BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthGetUncleCountByBlockNumber, new object[] { BlockParameter.AsString(block) });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public long NewBlockFilter()
+ {
+ string jsonResponse = in3.SendRpc(EthNewBlockFilter, new object[] { });
+ return (long)TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+
+ public bool UninstallFilter(long filter)
+ {
+ string jsonResponse = in3.SendRpc(EthUninstallFilter, new object[] { TypesMatcher.BigIntToPrefixedHex(filter) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public object Call(TransactionRequest request, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthCall, new object[] { MapTransactionToRpc(request), BlockParameter.AsString(block) });
+ if (request.IsFunctionInvocation())
+ {
+ return RpcHandler.From(jsonResponse);
+ }
+ else
+ {
+ return AbiDecode(request.Function, RpcHandler.From(jsonResponse));
+ }
+ }
+
+ public long EstimateGas(TransactionRequest request, BigInteger block)
+ {
+ string jsonResponse = in3.SendRpc(EthEstimateGas, new object[] { MapTransactionToRpc(request), BlockParameter.AsString(block) });
+ return (long)TypesMatcher.HexStringToBigint(RpcHandler.From(jsonResponse));
+ }
+
+ public long NewLogFilter(LogFilter filter)
+ {
+ string jsonResponse = in3.SendRpc(EthNewFilter, new object[] { filter.ToRPc() });
+ return Convert.ToInt64(RpcHandler.From(jsonResponse), 16);
+ }
+
+ public Log[] GetFilterChangesFromLogs(long id)
+ {
+ string jsonResponse = in3.SendRpc(EthGetFilterChanges, new object[] { TypesMatcher.BigIntToPrefixedHex((BigInteger)id) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Log[] GetFilterLogs(long id)
+ {
+ string jsonResponse = in3.SendRpc(EthGetFilterLogs, new object[] { TypesMatcher.BigIntToPrefixedHex((BigInteger)id) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Log[] GetLogs(LogFilter filter)
+ {
+ string jsonResponse = in3.SendRpc(EthGetLogs, new object[] { filter.ToRPc() });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public TransactionReceipt GetTransactionReceipt(string transactionHash)
+ {
+ string jsonResponse = in3.SendRpc(EthGetTransactionReceipt, new object[] { transactionHash });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string SendTransaction(TransactionRequest tx)
+ {
+ if (in3.Signer == null)
+ throw new SystemException("No Signer set. This is needed in order to sign transaction.");
+ if (tx.From == null)
+ throw new SystemException("No from address set");
+ if (!in3.Signer.CanSign(tx.From))
+ throw new SystemException("The from address is not supported by the signer");
+ tx = in3.Signer.PrepareTransaction(tx);
+
+ string jsonResponse = in3.SendRpc(EthSendTransaction, new object[] { MapTransactionToRpc(tx) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public Block GetUncleByBlockNumberAndIndex(BigInteger block, int pos)
+ {
+ string jsonResponse = in3.SendRpc(EthGetUncleByBlockNumberAndIndex,
+ new object[] { BlockParameter.AsString(block), TypesMatcher.BigIntToPrefixedHex(pos) });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ public string ENS(string name, ENSParameter? type = null)
+ {
+ string jsonResponse = in3.SendRpc(EthENS, new object[] { name, type });
+ return RpcHandler.From(jsonResponse);
+ }
+
+ // For sure this should not be here at all. As soon as there is a decoupled way to abiEncode, got to extract this to a wrapper (e.g.: adapter or a factory method on TransactionRpc itself.
+ private Rpc.Transaction MapTransactionToRpc(TransactionRequest tx)
+ {
+ Rpc.Transaction result = new Rpc.Transaction();
+
+ result.Data = tx.Data == null || tx.Data.Length < 2 ? "0x" : tx.Data;
+ if (!String.IsNullOrEmpty(tx.Function))
+ {
+ string fnData = AbiEncode(tx.Function, tx.Params);
+ if (fnData != null && fnData.Length > 2 && fnData.StartsWith("0x"))
+ result.Data += fnData.Substring(2 + (result.Data.Length > 2 ? 8 : 0));
+ }
+
+ result.To = tx.To;
+ result.From = tx.From;
+ if (tx.Value.HasValue)
+ {
+ result.Value = TypesMatcher.BigIntToPrefixedHex(tx.Value.Value);
+ }
+
+ if (tx.Nonce.HasValue)
+ {
+ result.Nonce = TypesMatcher.BigIntToPrefixedHex(tx.Nonce.Value);
+ }
+
+ if (tx.Gas.HasValue)
+ {
+ result.Gas = TypesMatcher.BigIntToPrefixedHex(tx.Gas.Value);
+ }
+
+ if (tx.GasPrice.HasValue)
+ {
+ result.GasPrice = TypesMatcher.BigIntToPrefixedHex(tx.GasPrice.Value);
+ }
+
+ if (result.Data == null || result.Data.Length < 2)
+ {
+ result.Data = "0x";
+ }
+ else
+ {
+ result.Data = TypesMatcher.AddHexPrefixer(result.Data);
+ }
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/Block.cs b/dotnet/In3/Eth1/Block.cs
new file mode 100644
index 000000000..4596f77be
--- /dev/null
+++ b/dotnet/In3/Eth1/Block.cs
@@ -0,0 +1,29 @@
+using System.Numerics;
+using System.Text.Json.Serialization;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public abstract class Block
+ {
+ [JsonPropertyName("totalDifficulty")] public string TotalDifficulty { get; set; }
+ [JsonPropertyName("gasLimit"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger GasLimit { get; set; }
+ [JsonPropertyName("extraData")] public string ExtraData { get; set; }
+ [JsonPropertyName("difficulty"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger Difficulty { get; set; }
+ [JsonPropertyName("author")] public string Author { get; set; }
+ [JsonPropertyName("transactionsRoot")] public string TransactionsRoot { get; set; }
+ [JsonPropertyName("receiptsRoot")] public string ReceiptsRoot { get; set; }
+ [JsonPropertyName("stateRoot")] public string StateRoot { get; set; }
+ [JsonPropertyName("timestamp"), JsonConverter(typeof(LongFromHexConverter))] public long Timestamp { get; set; }
+ [JsonPropertyName("sha3Uncles")] public string Sha3Uncles { get; set; }
+ [JsonPropertyName("size"), JsonConverter(typeof(LongFromHexConverter))] public long Size { get; set; }
+ // [JsonPropertyName("sealFields")] public string SealFields { get; set; }
+ [JsonPropertyName("hash")] public string Hash { get; set; }
+ [JsonPropertyName("logsBloom")] public string LogsBloom { get; set; }
+ [JsonPropertyName("mixHash")] public string MixHash { get; set; }
+ [JsonPropertyName("nonce")] public string Nonce { get; set; }
+ [JsonPropertyName("number"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger Number { get; set; }
+ [JsonPropertyName("parentHash")] public string ParentHash { get; set; }
+ [JsonPropertyName("uncles")] public string[] Uncles { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/Log.cs b/dotnet/In3/Eth1/Log.cs
new file mode 100644
index 000000000..d943d6774
--- /dev/null
+++ b/dotnet/In3/Eth1/Log.cs
@@ -0,0 +1,20 @@
+using System.Numerics;
+using System.Text.Json.Serialization;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public class Log
+ {
+ [JsonPropertyName("removed")] public bool Removed { get; set; }
+ [JsonPropertyName("logIndex"), JsonConverter(typeof(IntFromHexConverter))] public int LogIndex { get; set; }
+ [JsonPropertyName("transactionIndex"), JsonConverter(typeof(IntFromHexConverter))] public int TransactionIndex { get; set; }
+ [JsonPropertyName("transactionHash")] public string TransactionHash { get; set; }
+ [JsonPropertyName("blockHash")] public string BlockHash { get; set; }
+ [JsonPropertyName("blockNumber"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger BlockNumber { get; set; }
+ [JsonPropertyName("address")] public string Address { get; set; }
+ [JsonPropertyName("topics")] public string[] Topics { get; set; }
+ [JsonPropertyName("data")] public string Data { get; set; }
+ [JsonPropertyName("type")] public string Type { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/LogFilter.cs b/dotnet/In3/Eth1/LogFilter.cs
new file mode 100644
index 000000000..71811e2ca
--- /dev/null
+++ b/dotnet/In3/Eth1/LogFilter.cs
@@ -0,0 +1,29 @@
+using System.Numerics;
+using In3.Rpc;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public class LogFilter
+ {
+ public BigInteger? FromBlock { get; set; }
+ public BigInteger? ToBlock { get; set; }
+ public string Address { get; set; }
+ public object[] Topics { get; set; }
+ public string BlockHash { get; set; }
+
+ public LogFilter() {}
+
+ public Rpc.LogFilter ToRPc()
+ {
+ Rpc.LogFilter result = new Rpc.LogFilter();
+ if (FromBlock != null) result.FromBlock = BlockParameter.AsString(FromBlock.Value);
+ if (ToBlock != null) result.ToBlock = BlockParameter.AsString(ToBlock.Value);
+ result.Address = Address;
+ result.Topics = Topics;
+ result.BlockHash = BlockHash;
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/Transaction.cs b/dotnet/In3/Eth1/Transaction.cs
new file mode 100644
index 000000000..f7191fdb6
--- /dev/null
+++ b/dotnet/In3/Eth1/Transaction.cs
@@ -0,0 +1,30 @@
+using System.Numerics;
+using System.Security.Cryptography.X509Certificates;
+using System.Text.Json.Serialization;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public class Transaction
+ {
+ [JsonPropertyName("blockHash")] public string BlockHash { get; set; }
+ [JsonPropertyName("blockNumber"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger BlockNumber { get; set; }
+ [JsonPropertyName("chainId")] public string ChainId { get; set; }
+ [JsonPropertyName("creates")] public string Creates { get; set; }
+ [JsonPropertyName("from")] public string From { get; set; }
+ [JsonPropertyName("gas"), JsonConverter(typeof(LongFromHexConverter))] public long Gas { get; set; }
+ [JsonPropertyName("gasPrice"), JsonConverter(typeof(LongFromHexConverter))] public long GasPrice { get; set; }
+ [JsonPropertyName("hash")] public string Hash { get; set; }
+ [JsonPropertyName("input")] public string Input { get; set; }
+ [JsonPropertyName("nonce"), JsonConverter(typeof(LongFromHexConverter))] public long Nonce { get; set; }
+ [JsonPropertyName("publicKey")] public string PublicKey { get; set; }
+ [JsonPropertyName("r")] public string R { get; set; }
+ [JsonPropertyName("raw")] public string Raw { get; set; }
+ [JsonPropertyName("s")] public string S { get; set; }
+ [JsonPropertyName("standardV")] public string StandardV { get; set; }
+ [JsonPropertyName("to")] public string To { get; set; }
+ [JsonPropertyName("transactionIndex")] public string TransactionIndex { get; set; }
+ [JsonPropertyName("v")] public string V { get; set; }
+ [JsonPropertyName("value"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/TransactionBlock.cs b/dotnet/In3/Eth1/TransactionBlock.cs
new file mode 100644
index 000000000..28d2fc9d6
--- /dev/null
+++ b/dotnet/In3/Eth1/TransactionBlock.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Eth1
+{
+ public class TransactionBlock : Block
+ {
+ [JsonPropertyName("transactions")] public Transaction[] Transactions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/TransactionHashBlock.cs b/dotnet/In3/Eth1/TransactionHashBlock.cs
new file mode 100644
index 000000000..e86f1afc2
--- /dev/null
+++ b/dotnet/In3/Eth1/TransactionHashBlock.cs
@@ -0,0 +1,9 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Eth1
+{
+ public class TransactionHashBlock: Block
+ {
+ [JsonPropertyName("transactions")] public string[] Transactions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/TransactionReceipt.cs b/dotnet/In3/Eth1/TransactionReceipt.cs
new file mode 100644
index 000000000..a0f3e13ff
--- /dev/null
+++ b/dotnet/In3/Eth1/TransactionReceipt.cs
@@ -0,0 +1,22 @@
+using System.Numerics;
+using System.Text.Json.Serialization;
+using In3.Utils;
+
+namespace In3.Eth1
+{
+ public class TransactionReceipt
+ {
+ [JsonPropertyName("blockHash")] public string BlockHash { get; set; }
+ [JsonPropertyName("blockNumber"), JsonConverter(typeof(BigIntegerFromHexConverter))] public BigInteger BlockNumber { get; set; }
+ [JsonPropertyName("contractAddress")] public string ContractAddress { get; set; }
+ [JsonPropertyName("from")] public string From { get; set; }
+ [JsonPropertyName("transactionHash")] public string TransactionHash { get; set; }
+ [JsonPropertyName("transactionIndex"), JsonConverter(typeof(IntFromHexConverter))] public int TransactionIndex { get; set; }
+ [JsonPropertyName("to")] public string To { get; set; }
+ [JsonPropertyName("gasUsed"), JsonConverter(typeof(LongFromHexConverter))] public long GasUsed { get; set; }
+ [JsonPropertyName("logs")] public Log[] Logs { get; set; }
+ [JsonPropertyName("logsBloom")] public string LogsBloom { get; set; }
+ [JsonPropertyName("root")] public string Root { get; set; }
+ [JsonPropertyName("status"), JsonConverter(typeof(BoolFromHexConverter))] public bool Status { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Eth1/TransactionRequest.cs b/dotnet/In3/Eth1/TransactionRequest.cs
new file mode 100644
index 000000000..b1e8db534
--- /dev/null
+++ b/dotnet/In3/Eth1/TransactionRequest.cs
@@ -0,0 +1,19 @@
+using System.Numerics;
+
+namespace In3.Eth1
+{
+ public class TransactionRequest
+ {
+ public string From { get; set; }
+ public string To { get; set; }
+ public string Data { get; set; }
+ public BigInteger? Value { get; set; }
+ public long? Nonce { get; set; }
+ public long? Gas { get; set; }
+ public long? GasPrice { get; set; }
+ public string Function { get; set; }
+ public object[] Params { get; set; }
+
+ public bool IsFunctionInvocation() => string.IsNullOrEmpty(Function);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/IN3.cs b/dotnet/In3/IN3.cs
index 52b5da9d3..bd766ca5c 100644
--- a/dotnet/In3/IN3.cs
+++ b/dotnet/In3/IN3.cs
@@ -1,51 +1,52 @@
using System.Collections.Generic;
-using System.Text.Json;
+using In3.Configuration;
+using In3.Crypto;
using In3.Transport;
-using In3.Rpc;
using In3.Storage;
-using In3.Eth1;
using In3.Native;
+using In3.Utils;
namespace In3
{
public class IN3
{
- public Api Eth1 { get; }
- public NativeWrapper Native { get; }
- public Transport.Transport Transport { get; set; }
+ private NativeWrapper Native { get; }
+ public Eth1.Api Eth1 { get; }
+ public Transport.Transport Transport { get; set; }
public Storage.Storage Storage { get; set; }
+ public Signer Signer { get; set; }
+ public Crypto.Api Crypto { get; set; }
+ public Ipfs.Api Ipfs { get; set; }
+ public ClientConfiguration Configuration { get; }
+
private IN3(Chain chainId)
{
- Native = new DefaultNativeWrapper(this, chainId);
- Eth1 = new Api(this);
+ // Starting to get convoluted. Need to think of a better way.
Transport = new DefaultTransport();
Storage = new InMemoryStorage();
+ Signer = new SimpleWallet(this);
+ Native = new NativeWrapper(this, chainId);
+ Eth1 = new Eth1.Api(this);
+ Crypto = new Crypto.Api(this);
+ Ipfs = new Ipfs.Api(this);
+ Configuration = Native.ReadConfiguration();
}
- private IN3() {}
+ private IN3() { }
public static IN3 ForChain(Chain chainId)
{
return new IN3(chainId);
}
- public string SendRPCasObject(string method, object[] args, Dictionary in3 = null)
- {
- return Native.Send(ToRpc(method, args, in3));
- }
-
- private string ToRpc(string method, object[] parameters, Dictionary in3)
+ public string SendRpc(string method, object[] args, Dictionary in3 = null)
{
- JsonSerializerOptions options = new JsonSerializerOptions
+ if (Configuration.HasChanged())
{
- IgnoreNullValues = true
- };
-
- In3Rpc rpc = new In3Rpc();
- rpc.Method = method;
- rpc.Params = parameters;
- rpc.In3 = in3;
-
- return JsonSerializer.Serialize(rpc, options);
+ Native.ApplyConfiguration(Configuration);
+ }
+ return Native.Send(RpcHandler.To(method, args, in3));
}
+
+ ~IN3() => Native?.Free();
}
}
diff --git a/dotnet/In3/In3.csproj b/dotnet/In3/In3.csproj
index f6646fbaf..b5cf72f82 100644
--- a/dotnet/In3/In3.csproj
+++ b/dotnet/In3/In3.csproj
@@ -1,15 +1,35 @@
netcoreapp3.1
- https://github.com/slockit/in3-c
csharp
+ true
+ slock.it
+ slock.it
+ In3
+ Incubed client and provider for web3. Based on in3-c runtime.
+ osx-x64;linux-x64;win-x64;linux-arm64
+ ${version}
+ https://github.com/slockit/in3-c
+ git
+ Slockit.In3
+ AGPL-3.0-or-later
+ false
+ https://in3.readthedocs.io
+ https://in3.readthedocs.io
+ In3;C;Arm;X86;X64;Macos;Windows;Linux;Blockchain;Ethereum;Bitcoin;Ipfs
..\..\..\..\..\..\..\usr\share\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Text.Json.dll
-
-
-
+
+
+ true
+ runtimes
+
+
+ true
+ build
+
diff --git a/dotnet/In3/In3.targets b/dotnet/In3/In3.targets
new file mode 100644
index 000000000..a4cdb63c1
--- /dev/null
+++ b/dotnet/In3/In3.targets
@@ -0,0 +1,30 @@
+
+
+
+ \..\
+
+
+
+ libin3.dll
+ PreserveNewest
+
+
+
+
+ libin3.dylib
+ PreserveNewest
+
+
+
+
+ libin3.so
+ PreserveNewest
+
+
+
+
+ libin3.so
+ PreserveNewest
+
+
+
diff --git a/dotnet/In3/Ipfs/Api.cs b/dotnet/In3/Ipfs/Api.cs
new file mode 100644
index 000000000..03c5fd38a
--- /dev/null
+++ b/dotnet/In3/Ipfs/Api.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Text;
+using In3.Utils;
+
+namespace In3.Ipfs
+{
+ public class Api
+ {
+ private IN3 in3 { get; set; }
+
+ private const string IpfsPut = "ipfs_put";
+ private const string IpfsGet = "ipfs_get";
+
+ public Api(IN3 in3)
+ {
+ this.in3 = in3;
+ }
+
+ public byte[] Get(string multihash)
+ {
+ if (multihash == null) throw new ArgumentException();
+
+ string result = in3.SendRpc(IpfsGet, new object[] { multihash, IpfsEncoding.Base64.Value });
+ return RpcHandler.From(result);
+ }
+
+ public string Put(string content)
+ {
+ return Put(content == null ? null : Encoding.UTF8.GetBytes(content));
+ }
+
+ public string Put(byte[] content)
+ {
+ if (content == null) throw new ArgumentException();
+
+ string encodedContent = Convert.ToBase64String(content);
+ string result = in3.SendRpc(IpfsPut, new object[] { encodedContent });
+ return RpcHandler.From(result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Ipfs/IpfsEncoding.cs b/dotnet/In3/Ipfs/IpfsEncoding.cs
new file mode 100644
index 000000000..2aee6a52c
--- /dev/null
+++ b/dotnet/In3/Ipfs/IpfsEncoding.cs
@@ -0,0 +1,28 @@
+namespace In3.Ipfs
+{
+ // This is named IpfsEncoding to avoid name colision (while there is a namespace for that, its just better to avoid trouble for now at least while the class is internal)
+ internal class IpfsEncoding
+ {
+ private IpfsEncoding(string value)
+ {
+ Value = value;
+ }
+
+ public string Value { get; set; }
+
+ public static IpfsEncoding Base64
+ {
+ get { return new IpfsEncoding("base64"); }
+ }
+
+ public static IpfsEncoding Hex
+ {
+ get { return new IpfsEncoding("hex"); }
+ }
+
+ public static IpfsEncoding Utf8
+ {
+ get { return new IpfsEncoding("utf8"); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Native/DefaultNativeWrapper.cs b/dotnet/In3/Native/DefaultNativeWrapper.cs
deleted file mode 100644
index c22afd686..000000000
--- a/dotnet/In3/Native/DefaultNativeWrapper.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace In3.Native
-{
- internal class DefaultNativeWrapper : NativeWrapper
- {
- public IntPtr Ptr;
- public IN3 client { get; }
-
- public DefaultNativeWrapper(IN3 in3, Chain chainId)
- {
- client = in3;
- new NativeTransportHandler(this).RegisterNativeHandler();
- new NativeStorageHandler(this).RegisterNativeHandler();
- Ptr = in3_for_chain_auto_init(chainId);
- }
-
- public string Send(string jsonRpcRequest)
- {
- return in3_client_exec_req(Ptr, jsonRpcRequest);
- }
-
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern int in3_cache_init(IntPtr ptr);
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_register_eth_full();
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_register_eth_api();
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern IntPtr in3_for_chain_auto_init(Chain chainId);
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern string in3_client_exec_req(IntPtr ptr, string rpc);
- }
-}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeConfiguration.cs b/dotnet/In3/Native/NativeConfiguration.cs
new file mode 100644
index 000000000..80102f508
--- /dev/null
+++ b/dotnet/In3/Native/NativeConfiguration.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using In3.Configuration;
+using In3.Utils;
+
+namespace In3.Native
+{
+ internal class NativeConfiguration
+ {
+ public static ClientConfiguration Read(IntPtr client)
+ {
+ IntPtr jsonPointer = in3_get_config(client);
+ string jsonConfig = Marshal.PtrToStringUTF8(jsonPointer);
+ NativeUtils._free_(jsonPointer);
+
+ ClientConfiguration clientConf = JsonSerializer.Deserialize(jsonConfig);
+ clientConf.MarkSynced();
+ return clientConf;
+ }
+
+ internal static string SetConfig(IntPtr client, string val)
+ {
+ IntPtr jsonPointer = in3_configure(client, val);
+ if (jsonPointer != IntPtr.Zero)
+ {
+ string error = Marshal.PtrToStringUTF8(jsonPointer);
+ NativeUtils._free_(jsonPointer);
+ return error;
+ }
+
+ return null;
+ }
+
+ // Why this is an IntPtr and not a string: https://stackoverflow.com/questions/7322503/pinvoke-how-to-free-a-mallocd-string
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern IntPtr in3_get_config(IntPtr client);
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern IntPtr in3_configure(IntPtr client, string val);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeHandler.cs b/dotnet/In3/Native/NativeHandler.cs
new file mode 100644
index 000000000..f9a0f663c
--- /dev/null
+++ b/dotnet/In3/Native/NativeHandler.cs
@@ -0,0 +1,8 @@
+namespace In3.Native
+{
+ internal interface NativeHandler
+ {
+ public void RegisterNativeHandler();
+ public void UnregisterNativeHandler();
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeSignerHandler.cs b/dotnet/In3/Native/NativeSignerHandler.cs
new file mode 100644
index 000000000..72c2a361d
--- /dev/null
+++ b/dotnet/In3/Native/NativeSignerHandler.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using In3.Utils;
+
+namespace In3.Native
+{
+ internal class NativeSignerHandler : NativeHandler
+ {
+ private NativeWrapper Wrapper;
+
+ private GCHandle SignerGcHandle { get; set; }
+ private IntPtr SignerPtr { get; set; }
+
+ [StructLayout(LayoutKind.Sequential)] private struct bytes_t {
+ public IntPtr data;
+ public int len;
+ };
+
+ private unsafe delegate uint sign(void* ctx, uint type, bytes_t content, bytes_t account, IntPtr dst);
+
+ public NativeSignerHandler(NativeWrapper wrapper)
+ {
+ Wrapper = wrapper;
+ }
+
+ public void RegisterNativeHandler()
+ {
+ unsafe
+ {
+ sign signDel = Sign;
+ SignerGcHandle = GCHandle.Alloc(signDel);
+ IntPtr signPtr = Marshal.GetFunctionPointerForDelegate(signDel);
+ SignerPtr = in3_set_signer(Wrapper.NativeClientPointer, signPtr.ToPointer(), null, null);
+ }
+ }
+
+ public void UnregisterNativeHandler()
+ {
+ NativeUtils._free_(SignerPtr);
+ SignerGcHandle.Free();
+ }
+
+ private unsafe uint Sign(void* ctx, uint type, [MarshalAs(UnmanagedType.Struct)] bytes_t message, [MarshalAs(UnmanagedType.Struct)] bytes_t account, IntPtr dst)
+ {
+ byte[] accountBytes = new byte[account.len];
+ Marshal.Copy(account.data, accountBytes, 0, account.len);
+ string accountStr = TypesMatcher.BytesToHexString(accountBytes, account.len);
+
+ byte[] messageBytes = new byte[message.len];
+ Marshal.Copy(message.data, messageBytes, 0, message.len);
+ string messageStr = TypesMatcher.BytesToHexString(messageBytes, message.len);
+
+ String signedData = Wrapper.Client.Signer.Sign(messageStr, accountStr);
+
+ NativeUtils.hex_to_bytes(signedData, -1, dst, 65);
+ return 0;
+ }
+
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern unsafe IntPtr in3_set_signer(IntPtr client, void* sign, void* prepare_tx, void* wallet);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeStorageHandler.cs b/dotnet/In3/Native/NativeStorageHandler.cs
index 37a2c5b29..c77774f5e 100644
--- a/dotnet/In3/Native/NativeStorageHandler.cs
+++ b/dotnet/In3/Native/NativeStorageHandler.cs
@@ -5,11 +5,11 @@ namespace In3.Native
{
internal class NativeStorageHandler
{
- private DefaultNativeWrapper wrapper;
+ private NativeWrapper Wrapper;
- private static in3_storage_get_item GetItemDel { get; set; }
- private static in3_storage_set_item SetItemDel { get; set; }
- private static in3_storage_clear ClearDel { get; set; }
+ private in3_storage_get_item GetItemDel { get; set; }
+ private in3_storage_set_item SetItemDel { get; set; }
+ private in3_storage_clear ClearDel { get; set; }
private delegate byte[] in3_storage_get_item(IntPtr cptr, string key);
private delegate void in3_storage_set_item(IntPtr cptr, string key, byte[] content);
@@ -23,22 +23,27 @@ internal class NativeStorageHandler
public IntPtr cptr;
}
- public NativeStorageHandler(DefaultNativeWrapper wrapper)
+ public NativeStorageHandler(NativeWrapper wrapper)
{
- this.wrapper = wrapper;
+ Wrapper = wrapper;
}
public void RegisterNativeHandler()
{
- GetItemDel = GetItem;
- SetItemDel = SetItem;
- ClearDel = Clear;
+ in3_storage_get_item getItemDel = new in3_storage_get_item(GetItem);
+ GCHandle giCol = GCHandle.Alloc(getItemDel);
+
+ in3_storage_set_item setItemDel = new in3_storage_set_item(SetItem);
+ GCHandle siCol = GCHandle.Alloc(setItemDel);
+
+ in3_storage_clear clearDel = new in3_storage_clear(Clear);
+ GCHandle cCol = GCHandle.Alloc(clearDel);
in3_storage_handler_t storageHandler;
- storageHandler.get_item = GetItemDel;
- storageHandler.set_item = SetItemDel;
- storageHandler.clear = ClearDel;
- storageHandler.cptr = wrapper.Ptr;
+ storageHandler.get_item = getItemDel;
+ storageHandler.set_item = setItemDel;
+ storageHandler.clear = clearDel;
+ storageHandler.cptr = Wrapper.NativeClientPointer;
IntPtr myStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf()); // Allocate unmanaged memory for the struct
Marshal.StructureToPtr(storageHandler, myStructPtr, false);
@@ -47,17 +52,17 @@ public void RegisterNativeHandler()
private byte[] GetItem(IntPtr ignored, string key)
{
- return wrapper.client.Storage.GetItem(key);
+ return Wrapper.Client.Storage.GetItem(key);
}
private void SetItem(IntPtr ignored, string key, [MarshalAs(UnmanagedType.LPArray)] byte[] content)
{
- wrapper.client.Storage.SetItem(key, content);
+ Wrapper.Client.Storage.SetItem(key, content);
}
private bool Clear(IntPtr ignored)
{
- return wrapper.client.Storage.Clear();
+ return Wrapper.Client.Storage.Clear();
}
[DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_set_default_storage(IntPtr cacheStorage);
diff --git a/dotnet/In3/Native/NativeTransportHandler.cs b/dotnet/In3/Native/NativeTransportHandler.cs
index 71605c2cc..abc89de64 100644
--- a/dotnet/In3/Native/NativeTransportHandler.cs
+++ b/dotnet/In3/Native/NativeTransportHandler.cs
@@ -3,10 +3,12 @@
namespace In3.Native
{
- internal class NativeTransportHandler
+ internal class NativeTransportHandler : NativeHandler
{
- private static TransportHandler TransportDel { get; set; }
- private DefaultNativeWrapper wrapper { get; set; }
+ private NativeWrapper Wrapper { get; set; }
+
+ private GCHandle TransportGcHandle { get; set; }
+ private IntPtr TransportPtr { get; set; }
// structs
enum ErrorCode : int
@@ -15,7 +17,7 @@ enum ErrorCode : int
IN3_ERPC = -11
}
- [StructLayout(LayoutKind.Sequential)] private ref struct in3_request_t
+ [StructLayout(LayoutKind.Sequential)] private struct in3_request_t
{
[MarshalAs(UnmanagedType.LPStr)] public string payload;
// This esoteric thing came from here: https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-arrays
@@ -26,28 +28,46 @@ enum ErrorCode : int
public IntPtr times;
}
- [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)] private delegate int TransportHandler(ref in3_request_t ptr1);
+ [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)] private delegate int TransportHandler(IntPtr ptr1);
- public NativeTransportHandler(DefaultNativeWrapper wrapper)
+ public NativeTransportHandler(NativeWrapper wrapper)
{
- this.wrapper = wrapper;
+ Wrapper = wrapper;
}
public void RegisterNativeHandler()
{
- TransportDel = HandleRequest;
- in3_set_default_transport(TransportDel);
+ /*
+ * The code bellow is a combionation of three solutions:
+ * https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/367eeye0(v=vs.110)?redirectedfrom=MSDN
+ * https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/44ey4b32(v=vs.100)
+ * https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-a-delegate-as-a-callback-method
+ * The same logic SHOULD be applied to any function pointer stored in a struct (aka whose lifecycle goes beyond the higher order function invocation). In this context they are: transport, storage and signer.
+ */
+ unsafe
+ {
+ TransportHandler transportHandler = HandleRequest;
+ TransportGcHandle = GCHandle.Alloc(transportHandler);
+ IntPtr transportFunctionPtr = Marshal.GetFunctionPointerForDelegate(transportHandler);
+ in3_set_transport(Wrapper.NativeClientPointer, transportFunctionPtr.ToPointer());
+ }
+ }
+
+ public void UnregisterNativeHandler()
+ {
+ TransportGcHandle.Free();
}
- private int HandleRequest(ref in3_request_t req)
+ private int HandleRequest(IntPtr reqPtr)
{
+ in3_request_t req = Marshal.PtrToStructure(reqPtr);
ErrorCode err = ErrorCode.IN3_OK;
- string[] urls = GetAllStrings(req.urls, req.urls_len);
+ string[] urls = NativeUtils.GetAllStrings(req.urls, req.urls_len);
for (int i = 0; i < req.urls_len; i++)
{
try
{
- string result = wrapper.client.Transport.Handle(urls[i], req.payload);
+ string result = Wrapper.Client.Transport.Handle(urls[i], req.payload);
in3_req_add_response(req.results, i, false, result, result.Length);
}
catch (Exception ex)
@@ -59,19 +79,8 @@ private int HandleRequest(ref in3_request_t req)
return (int) err;
}
- // Heavily inspired by: https://stackoverflow.com/questions/1498931/marshalling-array-of-strings-to-char-in-c-sharp
- private string[] GetAllStrings(IntPtr ptr, int size) {
- string[] list = new string[size];
- for ( int i = 0; i < size; i++ ) {
- var strPtr = (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr));
- list[i] = Marshal.PtrToStringUTF8(strPtr);
- ptr = new IntPtr(ptr.ToInt64()+IntPtr.Size);
- }
- return list;
- }
-
[DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_req_add_response(IntPtr res, int index, bool is_error, string data, int data_len);
- [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_set_default_transport(TransportHandler transport);
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern unsafe void in3_set_transport(IntPtr client, void* transport);
}
}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeUtils.cs b/dotnet/In3/Native/NativeUtils.cs
new file mode 100644
index 000000000..268cc6423
--- /dev/null
+++ b/dotnet/In3/Native/NativeUtils.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace In3.Native
+{
+ internal class NativeUtils
+ {
+ // Heavily inspired by: https://stackoverflow.com/questions/1498931/marshalling-array-of-strings-to-char-in-c-sharp
+ public static string[] GetAllStrings(IntPtr ptr, int size) {
+ string[] list = new string[size];
+ for ( int i = 0; i < size; i++ ) {
+ var strPtr = (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr));
+ list[i] = Marshal.PtrToStringUTF8(strPtr);
+ ptr = new IntPtr(ptr.ToInt64()+IntPtr.Size);
+ }
+ return list;
+ }
+
+ [DllImport("libin3", CharSet = CharSet.Ansi)] public static extern void _free_(IntPtr ptr);
+
+ [DllImport("libin3", CharSet = CharSet.Ansi)] public static extern int hex_to_bytes(string buf, int len, IntPtr dst, int outbuf_size);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Native/NativeWrapper.cs b/dotnet/In3/Native/NativeWrapper.cs
index ded606569..ee5af74fd 100644
--- a/dotnet/In3/Native/NativeWrapper.cs
+++ b/dotnet/In3/Native/NativeWrapper.cs
@@ -1,7 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using In3.Configuration;
+
namespace In3.Native
{
- public interface NativeWrapper
+ internal class NativeWrapper
{
- public string Send(string jsonRpcRequest);
+ public IntPtr NativeClientPointer;
+ public IN3 Client { get; }
+ private List NativeHandlers { get; } = new List();
+
+ public NativeWrapper(IN3 in3, Chain chainId)
+ {
+ Client = in3;
+ NativeHandlers.Add(new NativeTransportHandler(this));
+ NativeHandlers.Add(new NativeSignerHandler(this));
+ new NativeStorageHandler(this).RegisterNativeHandler();
+
+ NativeClientPointer = in3_for_chain_auto_init(chainId);
+ NativeHandlers.ForEach(handler => handler.RegisterNativeHandler());
+ }
+
+ public string Send(string jsonRpcRequest)
+ {
+ IntPtr res = in3_client_exec_req(NativeClientPointer, jsonRpcRequest);
+ string str = Marshal.PtrToStringAnsi(res);
+ NativeUtils._free_(res);
+ return str;
+ }
+
+ public ClientConfiguration ReadConfiguration()
+ {
+ return NativeConfiguration.Read(NativeClientPointer);
+ }
+
+ public void ApplyConfiguration(ClientConfiguration configuration)
+ {
+ string error = NativeConfiguration.SetConfig(NativeClientPointer, configuration.ToJson());
+ if (!String.IsNullOrEmpty(error))
+ {
+ throw new ArgumentException(error, configuration.GetType().Name);
+ }
+ configuration.MarkSynced();
+ }
+
+ public void Free()
+ {
+ NativeHandlers.ForEach(handler => handler.UnregisterNativeHandler());
+ NativeHandlers.Clear();
+ if (NativeClientPointer != IntPtr.Zero)
+ {
+ in3_free(NativeClientPointer);
+ }
+ }
+
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern void in3_free(IntPtr ptr);
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern IntPtr in3_for_chain_auto_init(Chain chainId);
+ [DllImport("libin3", CharSet = CharSet.Ansi)] private static extern IntPtr in3_client_exec_req(IntPtr ptr, string rpc);
}
}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/Error.cs b/dotnet/In3/Rpc/Error.cs
new file mode 100644
index 000000000..72de26cdd
--- /dev/null
+++ b/dotnet/In3/Rpc/Error.cs
@@ -0,0 +1,10 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Rpc
+{
+ public class Error
+ {
+ [JsonPropertyName("code")] public int Code { get; set; }
+ [JsonPropertyName("message")] public string Message { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/Id.cs b/dotnet/In3/Rpc/Id.cs
new file mode 100644
index 000000000..775947e25
--- /dev/null
+++ b/dotnet/In3/Rpc/Id.cs
@@ -0,0 +1,29 @@
+namespace In3.Rpc
+{
+ public class Id
+ {
+ private string _value;
+
+ public Id(string id)
+ {
+ _value = id;
+ }
+
+ public Id(long id)
+ {
+ _value = id.ToString();
+ }
+
+ public long AsLong()
+ {
+ long result;
+ long.TryParse(_value, out result);
+ return result;
+ }
+
+ public string AsString()
+ {
+ return _value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/LogFilter.cs b/dotnet/In3/Rpc/LogFilter.cs
new file mode 100644
index 000000000..b0a3510ce
--- /dev/null
+++ b/dotnet/In3/Rpc/LogFilter.cs
@@ -0,0 +1,13 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Rpc
+{
+ public class LogFilter
+ {
+ [JsonPropertyName("fromBlock")] public string FromBlock { get; set; }
+ [JsonPropertyName("toBlock")] public string ToBlock { get; set; }
+ [JsonPropertyName("address")] public string Address { get; set; }
+ [JsonPropertyName("blockhash")] public string BlockHash { get; set; }
+ [JsonPropertyName("topics")] public object[] Topics { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/In3Rpc.cs b/dotnet/In3/Rpc/Request.cs
similarity index 93%
rename from dotnet/In3/Rpc/In3Rpc.cs
rename to dotnet/In3/Rpc/Request.cs
index 856d3d8c7..360f5201a 100644
--- a/dotnet/In3/Rpc/In3Rpc.cs
+++ b/dotnet/In3/Rpc/Request.cs
@@ -3,7 +3,7 @@
namespace In3.Rpc
{
- public class In3Rpc
+ public class Request
{
[JsonPropertyName("method")] public string Method { get; set; }
[JsonPropertyName("params")] public object[] Params { get; set; }
diff --git a/dotnet/In3/Rpc/Response.cs b/dotnet/In3/Rpc/Response.cs
new file mode 100644
index 000000000..59c210dfa
--- /dev/null
+++ b/dotnet/In3/Rpc/Response.cs
@@ -0,0 +1,13 @@
+using System.Text.Json.Serialization;
+using csharp.Utils;
+
+namespace In3.Rpc
+{
+ internal class Response
+ {
+ [JsonPropertyName("jsonrpc")] public string JsonRpc { get; set; }
+ [JsonPropertyName("id"), JsonConverter(typeof(IdConverter))] public Id Id { get; set; }
+ [JsonPropertyName("result")] public T Result { get; set; }
+ [JsonPropertyName("error")] public Error Error { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/RpcResult.cs b/dotnet/In3/Rpc/RpcResult.cs
deleted file mode 100644
index 336d335f7..000000000
--- a/dotnet/In3/Rpc/RpcResult.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace In3.Rpc
-{
- public class RpcResult
- {
- [JsonPropertyName("id")] public long Id { get; set; }
- [JsonPropertyName("result")] public T Result { get; set; }
- [JsonPropertyName("response")] public string Response { get; set; }
- }
-}
\ No newline at end of file
diff --git a/dotnet/In3/Rpc/Transaction.cs b/dotnet/In3/Rpc/Transaction.cs
new file mode 100644
index 000000000..9c8f35e6f
--- /dev/null
+++ b/dotnet/In3/Rpc/Transaction.cs
@@ -0,0 +1,15 @@
+using System.Text.Json.Serialization;
+
+namespace In3.Rpc
+{
+ public class Transaction
+ {
+ [JsonPropertyName("to")] public string To { get; set; }
+ [JsonPropertyName("from")] public string From { get; set; }
+ [JsonPropertyName("gas")] public string Gas { get; set; }
+ [JsonPropertyName("gasPrice")] public string GasPrice { get; set; }
+ [JsonPropertyName("value")] public string Value { get; set; }
+ [JsonPropertyName("nonce")] public string Nonce { get; set; }
+ [JsonPropertyName("data")] public string Data { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/BigIntegerJsonConverter.cs b/dotnet/In3/Utils/BigIntegerJsonConverter.cs
new file mode 100644
index 000000000..c80f24fd0
--- /dev/null
+++ b/dotnet/In3/Utils/BigIntegerJsonConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Numerics;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace In3.Utils
+{
+ internal class BigIntegerFromHexConverter : JsonConverter
+ {
+ public override BigInteger Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options) => TypesMatcher.HexStringToBigint(reader.GetString());
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ BigInteger intVal,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(TypesMatcher.BigIntToPrefixedHex(intVal));
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/BoolFromHexConverter.cs b/dotnet/In3/Utils/BoolFromHexConverter.cs
new file mode 100644
index 000000000..7acef1275
--- /dev/null
+++ b/dotnet/In3/Utils/BoolFromHexConverter.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using In3.Utils;
+
+namespace In3.Utils
+{
+ internal class BoolFromHexConverter : JsonConverter
+ {
+ // https://developer.mozilla.org/en-US/docs/Glossary/Falsy
+ private static readonly string[] FalsyValues = {
+ "false",
+ "0",
+ "-0",
+ "0n",
+ "",
+ "null",
+ "undefined",
+ "NaN"
+ };
+
+ private static readonly string[] HexsFalsyValues = {
+ "0x",
+ "0x0",
+ "0x00",
+ };
+
+ public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ string boolString = reader.GetString();
+ return !(HexsFalsyValues.Contains(boolString) || HexsFalsyValues.Contains(boolString));
+ }
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ bool boolVal,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(boolVal.ToString());
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/DictionaryChainObjectConverter.cs b/dotnet/In3/Utils/DictionaryChainObjectConverter.cs
new file mode 100644
index 000000000..01ea32dbc
--- /dev/null
+++ b/dotnet/In3/Utils/DictionaryChainObjectConverter.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using In3;
+using In3.Utils;
+
+namespace SystemTextJsonSamples
+{
+ // This is copied from: https://docs.microsoft.com/en-us/dotnet/api/system.enum.getvalues?view=netframework-4.8
+ // I had to narrow down to a more specific case because we dont want a key.ToString in the json writer.
+ internal class DictionaryChainObjectConverter : JsonConverterFactory
+ {
+ public override bool CanConvert(Type typeToConvert)
+ {
+ if (!typeToConvert.IsGenericType)
+ {
+ return false;
+ }
+
+ if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>))
+ {
+ return false;
+ }
+
+ return typeToConvert.GetGenericArguments()[0] == typeof(Chain);
+ }
+
+ public override JsonConverter CreateConverter(
+ Type type,
+ JsonSerializerOptions options)
+ {
+ Type keyType = type.GetGenericArguments()[0];
+ Type valueType = type.GetGenericArguments()[1];
+
+ JsonConverter converter = (JsonConverter)Activator.CreateInstance(
+ typeof(DictionaryEnumConverterInner<,>).MakeGenericType(
+ new Type[] { keyType, valueType }),
+ BindingFlags.Instance | BindingFlags.Public,
+ binder: null,
+ args: new object[] { options },
+ culture: null);
+
+ return converter;
+ }
+
+ private class DictionaryEnumConverterInner :
+ JsonConverter> where Chain : struct
+ {
+ private readonly JsonConverter _valueConverter;
+ private Type _keyType;
+ private Type _valueType;
+
+ public DictionaryEnumConverterInner(JsonSerializerOptions options)
+ {
+ // For performance, use the existing converter if available.
+ _valueConverter = (JsonConverter)options
+ .GetConverter(typeof(TValue));
+
+ // Cache the key and value types.
+ _keyType = typeof(In3.Chain);
+ _valueType = typeof(TValue);
+ }
+
+ public override Dictionary Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options)
+ {
+ if (reader.TokenType != JsonTokenType.StartObject)
+ {
+ throw new JsonException();
+ }
+
+ Dictionary dictionary = new Dictionary();
+
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonTokenType.EndObject)
+ {
+ return dictionary;
+ }
+
+ // Get the key.
+ if (reader.TokenType != JsonTokenType.PropertyName)
+ {
+ throw new JsonException();
+ }
+
+ // This is to convert the hex representation into a decimal base representation (which is later converted to string)
+ string propertyName = reader.GetString();
+ uint convertedPropertyName = Convert.ToUInt32(propertyName, 16);
+
+ // For performance, parse with ignoreCase:false first.
+ if (!Enum.TryParse(convertedPropertyName.ToString(), ignoreCase: false, out In3.Chain key) &&
+ !Enum.TryParse(convertedPropertyName.ToString(), ignoreCase: true, out key))
+ {
+ throw new JsonException(
+ $"Unable to convert \"{propertyName}\" to Enum \"{_keyType}\".");
+ }
+
+ // Get the value.
+ TValue v;
+ if (_valueConverter != null)
+ {
+ reader.Read();
+ v = _valueConverter.Read(ref reader, _valueType, options);
+ }
+ else
+ {
+ v = JsonSerializer.Deserialize(ref reader, options);
+ }
+
+ // Add to dictionary.
+ dictionary.Add(key, v);
+ }
+
+ throw new JsonException();
+ }
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ Dictionary dictionary,
+ JsonSerializerOptions options)
+ {
+ writer.WriteStartObject();
+
+ foreach (KeyValuePair kvp in dictionary)
+ {
+ writer.WritePropertyName(TypesMatcher.BigIntToPrefixedHex((int) kvp.Key));
+
+ if (_valueConverter != null)
+ {
+ _valueConverter.Write(writer, kvp.Value, options);
+ }
+ else
+ {
+ JsonSerializer.Serialize(writer, kvp.Value, options);
+ }
+ }
+
+ writer.WriteEndObject();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/IdConverter.cs b/dotnet/In3/Utils/IdConverter.cs
new file mode 100644
index 000000000..a533a0669
--- /dev/null
+++ b/dotnet/In3/Utils/IdConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using In3.Rpc;
+using In3.Utils;
+
+namespace csharp.Utils
+{
+ public class IdConverter : JsonConverter
+ {
+ public override Id Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.Number)
+ {
+ return new Id(reader.GetInt64());
+ }
+ else
+ {
+ return new Id(reader.GetString());
+ };
+ }
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ Id val,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(val.AsString());
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/IntFromHexConverter.cs b/dotnet/In3/Utils/IntFromHexConverter.cs
new file mode 100644
index 000000000..735496895
--- /dev/null
+++ b/dotnet/In3/Utils/IntFromHexConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace In3.Utils
+{
+ // HOW TO: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
+ internal class IntFromHexConverter : JsonConverter
+ {
+ public override int Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options) => (int) TypesMatcher.HexStringToBigint(reader.GetString());
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ int intVal,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(TypesMatcher.BigIntToPrefixedHex(intVal));
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/LongFromHexConverter.cs b/dotnet/In3/Utils/LongFromHexConverter.cs
new file mode 100644
index 000000000..bd5bcd014
--- /dev/null
+++ b/dotnet/In3/Utils/LongFromHexConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace In3.Utils
+{
+ // HOW TO: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
+ internal class LongFromHexConverter : JsonConverter
+ {
+ public override long Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options) => (long) TypesMatcher.HexStringToBigint(reader.GetString());
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ long intVal,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(TypesMatcher.BigIntToPrefixedHex(intVal));
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/ProofConverter.cs b/dotnet/In3/Utils/ProofConverter.cs
new file mode 100644
index 000000000..ec41429ab
--- /dev/null
+++ b/dotnet/In3/Utils/ProofConverter.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using In3.Configuration;
+
+namespace csharp.Utils
+{
+ internal class ProofConverter : JsonConverter
+ {
+ public override Proof Read(
+ ref Utf8JsonReader reader,
+ Type typeToConvert,
+ JsonSerializerOptions options) => Proof.FromValue(reader.GetString());
+
+ public override void Write(
+ Utf8JsonWriter writer,
+ Proof proofVal,
+ JsonSerializerOptions options) =>
+ writer.WriteStringValue(proofVal.Value);
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/RpcHandler.cs b/dotnet/In3/Utils/RpcHandler.cs
new file mode 100644
index 000000000..ab1ccc7fb
--- /dev/null
+++ b/dotnet/In3/Utils/RpcHandler.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using In3.Rpc;
+
+namespace In3.Utils
+{
+ public class RpcHandler
+ {
+ internal static T From(string json)
+ {
+ Response response = JsonSerializer.Deserialize>(json);
+ if (response.Error != null)
+ {
+ throw new SystemException(response.Error.Message);
+ }
+ return response.Result;
+ }
+
+ public static string To(string method, object[] parameters, Dictionary in3)
+ {
+ JsonSerializerOptions options = new JsonSerializerOptions
+ {
+ IgnoreNullValues = true
+ };
+
+ Request rpc = new Request();
+ rpc.Method = method;
+ rpc.Params = parameters;
+ rpc.In3 = in3;
+
+ return JsonSerializer.Serialize(rpc, options);
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/In3/Utils/TypesMatcher.cs b/dotnet/In3/Utils/TypesMatcher.cs
index e18510073..9959a170c 100644
--- a/dotnet/In3/Utils/TypesMatcher.cs
+++ b/dotnet/In3/Utils/TypesMatcher.cs
@@ -6,6 +6,23 @@ namespace In3.Utils
{
public class TypesMatcher
{
+ private static readonly char[] charsToTrim = new char[] { '0' };
+
+ public static string BytesToHexString(byte[] input, int len)
+ {
+ char[] result = new char[len * 2];
+ char[] hex = "0123456789abcdef".ToCharArray();
+
+ int i = 0, j = 0;
+ while (j < len) {
+ result[i++] = hex[(input[j] >> 4) & 0xF];
+ result[i++] = hex[input[j] & 0xF];
+ j++;
+ }
+
+ string zeroSufixedString = new string(result);
+ return $"0x{zeroSufixedString}";
+ }
public static BigInteger HexStringToBigint(string source)
{
if (String.IsNullOrWhiteSpace(source)) return BigInteger.Zero;
@@ -13,10 +30,31 @@ public static BigInteger HexStringToBigint(string source)
{
bool isNegative = source.StartsWith("-");
int startsAt = isNegative ? 3 : 2;
- BigInteger converted = BigInteger.Parse(source.Substring(startsAt), NumberStyles.AllowHexSpecifier);
- return isNegative ? converted * -1 : converted;
+
+ // Remove 0x prefix. Dotnet doesnt like it
+ string toConvert = source.Substring(isNegative ? 3 : 2);
+
+ // If this looks crazy, its because it is: https://docs.microsoft.com/en-us/dotnet/api/system.numerics.biginteger.parse?redirectedfrom=MSDN&view=netframework-4.8#System_Numerics_BigInteger_Parse_System_String_System_Globalization_NumberStyles_
+ toConvert = $"0{toConvert}";
+ BigInteger converted = BigInteger.Parse(toConvert, NumberStyles.AllowHexSpecifier);
+ return isNegative ? 0 - converted : converted;
}
return BigInteger.Parse(source, NumberStyles.AllowHexSpecifier);
}
+
+ public static string BigIntToPrefixedHex(BigInteger source)
+ {
+ // This initial if is to overcome the weird behavior of ".ToString("X")" and the corner case of trimming leading zeroes.
+ if (source == 0) return "0x0";
+ bool isPositive = source >= 0;
+ BigInteger toConvert = isPositive ? source : source * -1;
+ return isPositive ? $"0x{toConvert.ToString("X").TrimStart(charsToTrim)}" : $"-0x{toConvert.ToString("X").TrimStart(charsToTrim)}";
+ }
+
+ public static string AddHexPrefixer(string integerString)
+ {
+ if (integerString.StartsWith("0x") || integerString.StartsWith("-0x")) return integerString;
+ return BigIntToPrefixedHex(BigInteger.Parse(integerString));
+ }
}
}
\ No newline at end of file
diff --git a/dotnet/Test/ClientBuilder.cs b/dotnet/Test/ClientBuilder.cs
new file mode 100644
index 000000000..f549b0419
--- /dev/null
+++ b/dotnet/Test/ClientBuilder.cs
@@ -0,0 +1,57 @@
+using In3;
+using In3.Configuration;
+
+namespace Test
+{
+ public class ClientBuilder
+ {
+ private IN3 _client;
+ private Chain _chain;
+
+ public ClientBuilder(Chain chain) {
+ this._chain = chain;
+ }
+
+ public void CreateNewClient() {
+ _client = IN3.ForChain(_chain);
+ }
+
+ public void BuildTransport(string[][] fileNameTuples) {
+ StubTransport newTransport = new StubTransport();
+
+ foreach (string[] fileNameTuple in fileNameTuples) {
+ newTransport.AddMockedresponse(fileNameTuple[0], fileNameTuple[1]);
+ }
+
+ _client.Transport = newTransport;
+ }
+
+ public void BuildConfig()
+ {
+ ClientConfiguration clientConfig = _client.Configuration;
+
+ ChainConfiguration mainNetConfiguration = new ChainConfiguration(Chain.Mainnet, clientConfig);
+ mainNetConfiguration.NeedsUpdate = false;
+ mainNetConfiguration.Contract = "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f";
+ mainNetConfiguration.RegistryId = "0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb";
+
+ ChainConfiguration ipfsConfiguration = new ChainConfiguration(Chain.Ipfs, clientConfig);
+ ipfsConfiguration.NeedsUpdate = false;
+ ipfsConfiguration.Contract = "0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f";
+ ipfsConfiguration.RegistryId = "0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb";
+
+ clientConfig.RequestCount = 1;
+ clientConfig.AutoUpdateList = false;
+ clientConfig.Proof = Proof.None;
+ clientConfig.MaxAttempts = 1;
+ clientConfig.SignatureCount = 0;
+ }
+
+ public IN3 ConstructClient(string[][] fileNameTuples) {
+ CreateNewClient();
+ BuildTransport(fileNameTuples);
+ BuildConfig();
+ return _client;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Configuration/ConfigurationTest.cs b/dotnet/Test/Configuration/ConfigurationTest.cs
new file mode 100644
index 000000000..0b1f9a5db
--- /dev/null
+++ b/dotnet/Test/Configuration/ConfigurationTest.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Linq;
+using System.Text.Json;
+using In3;
+using In3.Configuration;
+using NUnit.Framework;
+
+namespace Test.Configuration
+{
+ public class ConfigurationTest
+ {
+ private IN3 _client;
+
+ [SetUp]
+ public void CreateClient()
+ {
+ _client = IN3.ForChain(Chain.Mainnet);
+ }
+
+ [Test]
+ public void ObjectHierarchy()
+ {
+ string nodeConfigOutputKey = "nodes";
+
+ ClientConfiguration clientConfig = _client.Configuration;
+
+ ChainConfiguration chainConfig = new ChainConfiguration(Chain.Goerli, clientConfig)
+ {
+ NeedsUpdate = false,
+ RegistryId = "0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb",
+ Contract = "0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab",
+ WhiteListContract = "0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab"
+ };
+
+ string jsonConfiguration1 = clientConfig.ToJson();
+
+ JsonDocument jsonObject1 = JsonDocument.Parse(jsonConfiguration1);
+ var propertiesName = jsonObject1.RootElement.EnumerateObject().Select(prop => prop.Name);
+
+ Assert.That(propertiesName.Contains(nodeConfigOutputKey));
+
+ NodeConfiguration nodeListConfig = new NodeConfiguration(chainConfig)
+ {
+ Props = 0x0, Url = "scheme://userinfo@host:port/path?query#fragment", Address = "0x0"
+ };
+
+ string jsonConfiguration2 = clientConfig.ToJson();
+ JsonDocument jsonObject2 = JsonDocument.Parse(jsonConfiguration2);
+
+ Assert.DoesNotThrow(() => jsonObject2
+ .RootElement
+ .GetProperty(nodeConfigOutputKey)
+ .GetProperty("0x5"));
+ }
+
+ [Test]
+ public void IsSynced()
+ {
+ ClientConfiguration config = _client.Configuration;
+ Assert.That(!config.HasChanged());
+
+ uint requestCount = 1;
+ bool autoUpdateList = false;
+ Proof proof = Proof.None;
+ uint maxAttempts = 1;
+ uint signatureCount = 0;
+
+ config.RequestCount = requestCount;
+ config.AutoUpdateList = autoUpdateList;
+ config.Proof = proof;
+ config.MaxAttempts = maxAttempts;
+ config.SignatureCount = signatureCount;
+
+ Assert.That(config.HasChanged());
+ _client.Eth1.GetChainId();
+ Assert.That(!config.HasChanged());
+ }
+
+ [Test]
+ public void DispatchRequestInvalidConfig()
+ {
+ ClientConfiguration config = _client.Configuration;
+
+ ChainConfiguration nodeConfig = new ChainConfiguration(Chain.Goerli, config)
+ {
+ NeedsUpdate = false,
+ RegistryId = "0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb",
+ Contract = "0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab",
+ WhiteListContract = "0xdd80249a0631cf0f1593c7a9c9f9b8545e6c88ab",
+ WhiteList = new [] {
+ "0x0123456789012345678901234567890123456789",
+ "0x1234567890123456789012345678901234567890"
+ }
+ };
+
+ Assert.Throws(() => _client.Eth1.GetGasPrice());
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Crypto/ApiTest.cs b/dotnet/Test/Crypto/ApiTest.cs
new file mode 100644
index 000000000..f059d3b0a
--- /dev/null
+++ b/dotnet/Test/Crypto/ApiTest.cs
@@ -0,0 +1,84 @@
+using System;
+using In3;
+using In3.Crypto;
+using NUnit.Framework;
+
+namespace Test.Crypto
+{
+ public class ApiTest
+ {
+ private IN3 in3;
+
+ [SetUp]
+ public void Setup()
+ {
+ ClientBuilder _builder = new ClientBuilder(Chain.Mainnet);
+ in3 = _builder.ConstructClient(new string[][] {});
+ }
+
+ [Test]
+ public void SignData() {
+ string msg = "0x0102030405060708090a0b0c0d0e0f";
+ string key = "0xa8b8759ec8b59d7c13ef3630e8530f47ddb47eba12f00f9024d3d48247b62852";
+ SignedData signature = in3.Crypto.SignData(msg, key, SignatureType.Raw);
+
+ Assert.That(signature.Message, Is.EqualTo("0x0102030405060708090a0b0c0d0e0f"));
+ Assert.That(signature.MessageHash, Is.EqualTo("0x1d4f6fccf1e27711667605e29b6f15adfda262e5aedfc5db904feea2baa75e67"));
+ Assert.That(signature.Signature, Is.EqualTo("0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e95792264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e1521b"));
+ Assert.That(signature.R, Is.EqualTo("0xa5dea9537d27e4e20b6dfc89fa4b3bc4babe9a2375d64fb32a2eab04559e9579"));
+ Assert.That(signature.S, Is.EqualTo("0x2264ad1fb83be70c145aec69045da7986b95ee957fb9c5b6d315daa5c0c3e152"));
+ Assert.That(signature.V, Is.EqualTo(27));
+ }
+
+ [Test]
+ public void DecryptKey()
+ {
+ string 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\"}}";
+ string passphrase = "test";
+ string result = in3.Crypto.DecryptKey(key, passphrase);
+ Assert.That(result, Is.EqualTo("0x1ff25594a5e12c1e31ebd8112bdf107d217c1393da8dc7fc9d57696263457546"));
+ }
+
+ [Test]
+ public void Pk2Public()
+ {
+ string privateKey = "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a";
+
+ string publicKey = in3.Crypto.Pk2Public(privateKey);
+
+ Assert.That(publicKey, Is.EqualTo("0x0903329708d9380aca47b02f3955800179e18bffbb29be3a644593c5f87e4c7fa960983f78186577eccc909cec71cb5763acd92ef4c74e5fa3c43f3a172c6de1"));
+ }
+
+ [Test]
+ public void Pk2Address()
+ {
+ string privateKey = "0x0fd65f7da55d811634495754f27ab318a3309e8b4b8a978a50c20a661117435a";
+
+ string address = in3.Crypto.Pk2Address(privateKey);
+
+ Assert.That(address, Is.EqualTo("0xdc5c4280d8a286f0f9c8f7f55a5a0c67125efcfd"));
+ }
+
+ [Test]
+ public void EcRecover()
+ {
+ String msg = "0x487b2cbb7997e45b4e9771d14c336b47c87dc2424b11590e32b3a8b9ab327999";
+ String signature = "0x0f804ff891e97e8a1c35a2ebafc5e7f129a630a70787fb86ad5aec0758d98c7b454dee5564310d497ddfe814839c8babd3a727692be40330b5b41e7693a445b71c";
+
+ Account account = in3.Crypto.EcRecover(msg, signature, SignatureType.Hash);
+
+ Assert.That(account.PublicKey, Is.EqualTo("0x94b26bafa6406d7b636fbb4de4edd62a2654eeecda9505e9a478a66c4f42e504c4481bad171e5ba6f15a5f11c26acfc620f802c6768b603dbcbe5151355bbffb"));
+ Assert.That(account.Address, Is.EqualTo("0xf68a4703314e9a9cf65be688bd6d9b3b34594ab4"));
+ }
+
+ [Test]
+ public void Sha3()
+ {
+ string data = "0x68656c6c6f20776f726c64";
+
+ string result = in3.Crypto.Sha3(data);
+
+ Assert.That(result, Is.EqualTo("0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Eth1/ApiTest.cs b/dotnet/Test/Eth1/ApiTest.cs
new file mode 100644
index 000000000..19d5f694b
--- /dev/null
+++ b/dotnet/Test/Eth1/ApiTest.cs
@@ -0,0 +1,510 @@
+using System.Numerics;
+using In3;
+using In3.Crypto;
+using In3.Eth1;
+using In3.Utils;
+using NUnit.Framework;
+
+namespace Test.Eth1
+{
+ public class ApiTest
+ {
+ private ClientBuilder _builder;
+
+ [SetUp]
+ public void Setup()
+ {
+ _builder = new ClientBuilder(Chain.Mainnet);
+ }
+
+ [Test]
+ public void BlockNumber()
+ {
+ string[][] mockedResponses =
+ {
+ new[] {"eth_blockNumber", "eth_blockNumber.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ BigInteger result = in3.Eth1.BlockNumber();
+
+ Assert.That(result, Is.EqualTo(new BigInteger(3220)));
+ }
+
+ [Test]
+ public void BlockByNumber()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getBlockByNumber", "eth_getBlockByNumber.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Block latest = in3.Eth1.GetBlockByNumber(BlockParameter.Earliest);
+
+ Assert.That(latest.Number, Is.EqualTo(new BigInteger(0)));
+ Assert.That(latest.Size, Is.EqualTo(540));
+ }
+
+ [Test]
+ public void BlockByHash()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getBlockByHash", "eth_getBlockByHash.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Block latest = in3.Eth1.GetBlockByHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3");
+
+ Assert.That(latest.Number, Is.EqualTo(new BigInteger(0)));
+ Assert.That(latest.Size, Is.EqualTo(540));
+ }
+
+ [Test]
+ public void AbiEncode()
+ {
+ IN3 in3 = _builder.ConstructClient(new string[][] {});
+
+ string signature = "getBalance(address)";
+ string[] args = {"0x1234567890123456789012345678901234567890"};
+ string expectedEncoded = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890";
+
+ string result = in3.Eth1.AbiEncode(signature, args);
+
+ Assert.That(result, Is.EqualTo(expectedEncoded));
+ }
+
+ [Test]
+ public void AbiDecode()
+ {
+ IN3 in3 = _builder.ConstructClient(new string[][] {});
+
+ string signature = "(address,uint256)";
+ string encoded = "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005";
+ string[] expectedDecode = { "0x1234567890123456789012345678901234567890", "0x05" };
+
+ string[] result = in3.Eth1.AbiDecode(signature, encoded);
+
+ Assert.That(result, Is.EqualTo(expectedDecode));
+ }
+
+ [Test]
+ public void GetGasPrice()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_gasPrice", "eth_gasPrice.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ BigInteger currentGasPrice = in3.Eth1.GetGasPrice();
+
+ Assert.That(currentGasPrice, Is.EqualTo(new BigInteger(2100000000)));
+ }
+
+ [Test]
+ public void GetChainId()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_estimateGas", "eth_estimateGas.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Chain currentChain = in3.Eth1.GetChainId();
+ Assert.That(currentChain, Is.EqualTo(Chain.Mainnet));
+ }
+
+ [Test]
+ public void GetCode()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getCode", "eth_getCode.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ string response = in3.Eth1.GetCode("0xdAC17F958D2ee523a2206206994597C13D831ec7", BlockParameter.Latest);
+
+ Assert.NotNull(response);
+ }
+
+ [Test]
+ public void GetStorageAt()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getStorageAt", "eth_getStorageAt.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ string storage = in3.Eth1.GetStorageAt("0x862174623bc39e57de552538f424806b947d3d05", 0, BlockParameter.Latest);
+
+ Assert.That(storage, Is.EqualTo("0x0000000000000000000000000000000000000000000000000000000000000000"));
+ }
+
+ [Test]
+ public void GetBlockTransactionCountByHash()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getBlockTransactionCountByHash", "eth_getBlockTransactionCountByHash.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ long transactionCount = in3.Eth1
+ .GetBlockTransactionCountByHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3");
+
+ Assert.That(transactionCount, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetBlockTransactionCountByNumber()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getBlockTransactionCountByNumber", "eth_getBlockTransactionCountByNumber.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ long transactionCount = in3.Eth1
+ .GetBlockTransactionCountByNumber(9298869);
+
+ Assert.That(transactionCount, Is.EqualTo(121));
+ }
+
+ [Test]
+ public void GetTransactionByBlockHashAndIndex()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getTransactionByBlockHashAndIndex", "eth_getTransactionByBlockHashAndIndex.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Transaction tx = in3.Eth1.GetTransactionByBlockHashAndIndex(
+ "0xd03f4a0ce830ce568be08aa37bc0a72374e92da5b388e839b35f24a144a5085d", 1);
+ Assert.That(tx.Value, Is.EqualTo(new BigInteger(48958690000000000)));
+ }
+
+ [Test]
+ public void GetTransactionByBlockNumberAndIndex()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getTransactionByBlockNumberAndIndex", "eth_getTransactionByBlockNumberAndIndex.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Transaction tx = in3.Eth1.GetTransactionByBlockNumberAndIndex(9319093, 1);
+
+ Assert.That(tx.Value, Is.EqualTo(new BigInteger(48958690000000000)));
+ Assert.That(tx.From, Is.EqualTo("0xe3649077ce21a48caf34041e983b92e332e80fd9"));
+ }
+
+ [Test]
+ public void GetTransactionByHash()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getTransactionByHash", "eth_getTransactionByHash.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Transaction tx = in3.Eth1.GetTransactionByHash("0x6188bf0672c005e30ad7c2542f2f048521662e30c91539d976408adf379bdae2");
+
+ Assert.That(tx.BlockHash, Is.EqualTo("0x8220e66456e40636bff3a440832c9f179e4811d4e28269c7ab70142c3e5f9be2"));
+ Assert.That(tx.From, Is.EqualTo("0x3a9e354dee60df25c0389badafec8457e36ebfd2"));
+ }
+
+ [Test]
+ public void GetTransactionCount()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_getTransactionCount", "eth_getTransactionCount.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ string from = "0x7fc7032e731f5bcbd4843406945acaf917087fde";
+
+ long transactionCount = in3.Eth1.GetTransactionCount(from, BlockParameter.Latest);
+
+ Assert.That(transactionCount, Is.EqualTo(19));
+ }
+
+ [Test]
+ public void SendRawTransaction()
+ {
+ string[][] mockedResponses = {
+ new [] {"eth_sendRawTransaction", "eth_sendRawTransaction_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ string rawTransaction = "0xf8671b8477359400825208943940256b93c4be0b1d5931a6a036608c25706b0c8405f5e100802da0278d2c010a59688fc12a55563d81239b1dc7e3d9c6a535b34600329b0c640ad8a03894daf8d7c25b56caec71b695c5f6b1b6fd903ecfa441b2c4e15fd1c72c54a9";
+
+ string hash = in3.Eth1.SendRawTransaction(rawTransaction);
+
+ Assert.That(hash, Is.EqualTo("0xd55a8b0cf4896ffbbb10b125bf20d89c8006f42cc327a9859c59ac54e439b388"));
+ }
+
+ [Test]
+ public void SendTransaction()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_gasPrice", "eth_gasPrice.json"},
+ new[] {"eth_estimateGas", "eth_estimateGas.json"},
+ new[] {"eth_getTransactionCount", "eth_getTransactionCount.json"},
+ new[] {"eth_sendRawTransaction", "eth_sendRawTransaction.json"}
+ };
+
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+ string excpectedReceipt = "0xd5651b7c0b396c16ad9dc44ef0770aa215ca795702158395713facfbc9b55f38";
+ string pk = "0x0829B3C639A3A8F2226C8057F100128D4F7AE8102C92048BA6DE38CF4D3BC6F1";
+ SimpleWallet sw = (SimpleWallet) in3.Signer;
+ string from = sw.AddRawKey(pk);
+
+ TransactionRequest request = new TransactionRequest();
+ request.From = from;
+ request.To = "0x3940256B93c4BE0B1d5931A6A036608c25706B0c";
+ request.Gas = 21000;
+ request.Value = 100000000;
+
+ object receipt = in3.Eth1.SendTransaction(request);
+ Assert.That(receipt, Is.EqualTo(excpectedReceipt));
+ }
+
+ [Test]
+ public void ChecksumAddress()
+ {
+ IN3 in3 = _builder.ConstructClient(new string[][] {});
+
+ string expectedAddress = "0xBc0ea09C1651A3D5D40Bacb4356FB59159A99564";
+ string address = in3.Eth1.ChecksumAddress("0xbc0ea09c1651a3d5d40bacb4356fb59159a99564");
+
+ Assert.That(address, Is.EqualTo(expectedAddress));
+ }
+
+ [Test]
+ public void GetUncleCountByBlockHash()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getUncleCountByBlockHash", "eth_getUncleCountByBlockHash.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ long uncleCount = in3.Eth1.GetUncleCountByBlockHash("0x884aaab2f9116742e693ced034a2dff840b45f21709025f7d69cde26d071068b");
+
+ Assert.That(uncleCount, Is.EqualTo(1));
+ }
+
+ [Test]
+ public void GetUncleCountByBlockNumber()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getUncleCountByBlockNumber", "eth_getUncleCountByBlockNumber.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ long uncleCount = in3.Eth1.GetUncleCountByBlockNumber(9830239);
+
+ Assert.That(uncleCount, Is.EqualTo(2));
+ }
+
+ [Test]
+ public void NewBlockFilter()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_blockNumber", "eth_blockNumber_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ long filterId = in3.Eth1.NewBlockFilter();
+
+ Assert.That(filterId > 0);
+
+ // Given the same mock response, this should increment the filter_id
+ long filterId2 = in3.Eth1.NewBlockFilter();
+
+ Assert.That(filterId + 1, Is.EqualTo(filterId2));
+ }
+
+ [Test]
+ public void UninstallFilter()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_blockNumber", "eth_blockNumber_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ LogFilter filter = new LogFilter();
+ filter.Address = "0xF0AD5cAd05e10572EfcEB849f6Ff0c68f9700455";
+ long filterId = in3.Eth1.NewLogFilter(filter);
+
+ bool success1 = in3.Eth1.UninstallFilter(filterId);
+ Assert.That(success1);
+ bool success2 = in3.Eth1.UninstallFilter(filterId);
+ Assert.That(!success2);
+ }
+
+ [Test]
+ public void Call()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_call", "eth_call_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ TransactionRequest request = new TransactionRequest();
+ request.To = "0x2736D225f85740f42D17987100dc8d58e9e16252";;
+ request.Function = "servers(uint256):(string,address,uint32,uint256,uint256,address)";
+ request.Params = new object[] { 1 };
+
+ string[] res1 = (string[]) in3.Eth1.Call(request, BlockParameter.Latest);
+
+ Assert.That(res1.Length, Is.EqualTo(6));
+ Assert.That(res1[0], Is.EqualTo("https://in3.slock.it/mainnet/nd-4"));
+ Assert.That(res1[1], Is.EqualTo("0xbc0ea09c1651a3d5d40bacb4356fb59159a99564"));
+ Assert.That(res1[2], Is.EqualTo("0xffff"));
+ Assert.That(res1[3], Is.EqualTo("0xffff"));
+ }
+
+ [Test]
+ public void GetBalance()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getBalance", "eth_getBalance.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ BigInteger expectedBalance = 3646260000000000000;
+ string address = "0x4144FFD5430a8518fa2d84ef5606Fd7e1921cE27";
+ BigInteger balance = in3.Eth1.GetBalance(address, BlockParameter.Latest);
+
+ Assert.That(balance, Is.EqualTo(expectedBalance));
+ }
+
+ [Test]
+ public void EstimateGas()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_estimateGas", "eth_estimateGas.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+ string pk = "0x0829B3C639A3A8F2226C8057F100128D4F7AE8102C92048BA6DE38CF4D3BC6F1";
+ SimpleWallet wallet = (SimpleWallet) in3.Signer;
+ string from = wallet.AddRawKey(pk);
+
+ long expectedGasEstimate = 21000;
+ TransactionRequest tx = new TransactionRequest();
+ tx.GasPrice = 1;
+ tx.From = from;
+ tx.To = "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8";
+
+ long gasEstimate = in3.Eth1.EstimateGas(tx, BlockParameter.Latest);
+ Assert.That(gasEstimate, Is.EqualTo(expectedGasEstimate));
+ }
+
+ [Test]
+ public void NewLogFilter()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_blockNumber", "eth_blockNumber_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ LogFilter filter = new LogFilter();
+ filter.Address = "0xF0AD5cAd05e10572EfcEB849f6Ff0c68f9700455";
+
+ long filterId = in3.Eth1.NewLogFilter(filter);
+
+ Assert.That(filterId > 0);
+
+ // Given the same mock response, this should increment the filter_id
+ long filterId2 = in3.Eth1.NewLogFilter(filter);
+
+ Assert.That(filterId2, Is.EqualTo(filterId + 1));
+ }
+
+ [Test]
+ public void GetFilterChanges()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_blockNumber", "eth_blockNumber_2.json"},
+ new[] {"eth_getLogs", "eth_getLogs_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ LogFilter filter = new LogFilter();
+ filter.Address = "0x1c81079b0752881f3231318a1355e21de26bbeb5";
+ filter.FromBlock = 2050343;
+ long filterId = in3.Eth1.NewLogFilter(filter);
+
+ Log[] logs1 = in3.Eth1.GetFilterChangesFromLogs(filterId);
+
+ Assert.That(logs1.Length, Is.GreaterThan(0));
+
+ Log[] logs2 = in3.Eth1.GetFilterChangesFromLogs(filterId);
+
+ Assert.That(logs2.Length, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetFilterLogs()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_blockNumber", "eth_blockNumber_2.json"},
+ new[] {"eth_getLogs", "eth_getLogs_1.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ LogFilter filter = new LogFilter();
+ filter.Address = "0x1c81079b0752881f3231318a1355e21de26bbeb5";
+ filter.FromBlock = 2050343;
+ long filterId = in3.Eth1.NewLogFilter(filter);
+
+ Log[] logs1 = in3.Eth1.GetFilterChangesFromLogs(filterId);
+
+ Assert.That(logs1.Length, Is.GreaterThan(0));
+
+ Log[] logs2 = in3.Eth1.GetFilterChangesFromLogs(filterId);
+
+ Assert.That(logs2.Length, Is.EqualTo(0));
+ }
+
+ [Test]
+ public void GetLogs()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getLogs", "eth_getLogs.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ LogFilter filter = new LogFilter();
+ filter.FromBlock = TypesMatcher.HexStringToBigint("0x834B77");
+ filter.ToBlock = TypesMatcher.HexStringToBigint("0x834B77");
+ filter.Address = "0xdac17f958d2ee523a2206206994597c13d831ec7";
+
+ Log[] response = in3.Eth1.GetLogs(filter);
+
+ Assert.That(response[0].TransactionHash, Is.EqualTo("0x20be6d27ed6a4c99c5dbeeb9081e114a9b400c52b80c4d10096c94ad7d3c1af6"));
+ }
+
+ [Test]
+ public void GetTransactionReceipt()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getTransactionReceipt", "eth_getTransactionReceipt.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ TransactionReceipt receipt = in3.Eth1 .GetTransactionReceipt("0x6188bf0672c005e30ad7c2542f2f048521662e30c91539d976408adf379bdae2");
+ Assert.That(receipt.To, Is.EqualTo("0x5b8174e20996ec743f01d3b55a35dd376429c596"));
+ Assert.That(receipt.Status);
+ Assert.That(receipt.Logs[0].Address, Is.EqualTo("0x5b8174e20996ec743f01d3b55a35dd376429c596"));
+ }
+
+ [Test]
+ public void GetUncleByBlockNumberAndIndex()
+ {
+ string[][] mockedResponses = {
+ new[] {"eth_getUncleByBlockNumberAndIndex", "eth_getUncleByBlockNumberAndIndex.json"}
+ };
+ IN3 in3 = _builder.ConstructClient(mockedResponses);
+
+ Block uncle = in3.Eth1.GetUncleByBlockNumberAndIndex(9317999, 0);
+
+ Assert.That(uncle.Number, Is.EqualTo(new BigInteger(9317998)));
+ Assert.That(uncle.Size, Is.EqualTo(37088));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Eth1/TransactionRequestTest.cs b/dotnet/Test/Eth1/TransactionRequestTest.cs
new file mode 100644
index 000000000..837623d62
--- /dev/null
+++ b/dotnet/Test/Eth1/TransactionRequestTest.cs
@@ -0,0 +1,21 @@
+using In3.Native;
+using NUnit.Framework;
+using System.Text.Json;
+
+namespace Test.Eth1
+{
+ public class TransactionRequestTest
+ {
+ [Test]
+ public void AbiEncode()
+ {
+ string signature = "getBalance(address)";
+ string[] args = {
+ "0x1234567890123456789012345678901234567890"
+ };
+
+ string expected = "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890";
+ Assert.That(result, Is.EqualTo(expected));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Ipfs/ApiTest.cs b/dotnet/Test/Ipfs/ApiTest.cs
new file mode 100644
index 000000000..cefba85b2
--- /dev/null
+++ b/dotnet/Test/Ipfs/ApiTest.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Numerics;
+using System.Text;
+using System.Text.Unicode;
+using In3;
+using NUnit.Framework;
+
+namespace Test.Ipfs
+{
+ public class ApiTest
+ {
+ private IN3 _in3;
+
+ [SetUp]
+ public void Setup()
+ {
+ string[][] mockedResponses = {
+ new[] {"ipfs_get", "ipfs_get.json"},
+ new[] {"ipfs_put", "ipfs_put.json"}
+ };
+
+ ClientBuilder builder = new ClientBuilder(Chain.Ipfs); ;
+ _in3 = builder.ConstructClient(mockedResponses);
+ }
+
+ [Test]
+ public void Put_Success()
+ {
+ string content = "Lorem ipsum dolor sit amet";
+
+ string multihash = _in3.Ipfs.Put(content);
+
+ Assert.NotNull(multihash);
+ Assert.That(multihash, Is.EqualTo("QmbGySCLuGxu2GxVLYWeqJW9XeyjGFvpoZAhGhXDGEUQu8"));
+ }
+
+ [Test]
+ public void Put_Failure()
+ {
+ string nullString = null;
+
+ Assert.Throws(() => _in3.Ipfs.Put(nullString));
+ }
+
+ [Test]
+ public void Get_Success()
+ {
+ string multihash = "QmbGySCLuGxu2GxVLYWeqJW9XeyjGFvpoZAhGhXDGEUQu8";
+
+ byte[] content = _in3.Ipfs.Get(multihash);
+
+ Assert.NotNull(content);
+ Assert.That(content, Is.EqualTo(Encoding.UTF8.GetBytes("Lorem ipsum dolor sit amet")));
+ }
+
+ [Test]
+ public void Get_Failure()
+ {
+ string nullString = null;
+
+ Assert.Throws(() => _in3.Ipfs.Get(nullString));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_blockNumber.json b/dotnet/Test/Responses/eth_blockNumber.json
new file mode 100644
index 000000000..1b40670db
--- /dev/null
+++ b/dotnet/Test/Responses/eth_blockNumber.json
@@ -0,0 +1,6 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0xc94"
+ }
+]
diff --git a/dotnet/Test/Responses/eth_blockNumber_1.json b/dotnet/Test/Responses/eth_blockNumber_1.json
new file mode 100644
index 000000000..e66d1a7c1
--- /dev/null
+++ b/dotnet/Test/Responses/eth_blockNumber_1.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x8e4daa",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9324167,
+ "execTime": 45,
+ "rpcTime": 45,
+ "rpcCount": 1,
+ "currentBlock": 9325994,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_blockNumber_2.json b/dotnet/Test/Responses/eth_blockNumber_2.json
new file mode 100644
index 000000000..2862cc871
--- /dev/null
+++ b/dotnet/Test/Responses/eth_blockNumber_2.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0x1f4a2f",
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 107,
+ "rpcTime": 107,
+ "rpcCount": 1,
+ "currentBlock": 2050607,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_blockNumber_3.json b/dotnet/Test/Responses/eth_blockNumber_3.json
new file mode 100644
index 000000000..438062af7
--- /dev/null
+++ b/dotnet/Test/Responses/eth_blockNumber_3.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0x1f5c2c",
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 94,
+ "rpcTime": 94,
+ "rpcCount": 1,
+ "currentBlock": 2055213,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_blockNumber_4.json b/dotnet/Test/Responses/eth_blockNumber_4.json
new file mode 100644
index 000000000..950cbd319
--- /dev/null
+++ b/dotnet/Test/Responses/eth_blockNumber_4.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0x1f5c2d",
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 94,
+ "rpcTime": 94,
+ "rpcCount": 1,
+ "currentBlock": 2055213,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_call_1.json b/dotnet/Test/Responses/eth_call_1.json
new file mode 100644
index 000000000..5959de791
--- /dev/null
+++ b/dotnet/Test/Responses/eth_call_1.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc":"2.0",
+ "id":1,
+ "result":"0x00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000bc0ea09c1651a3d5d40bacb4356fb59159a99564000000000000000000000000000000000000000000000000000000000000ffff000000000000000000000000000000000000000000000000000000000000ffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002168747470733a2f2f696e332e736c6f636b2e69742f6d61696e6e65742f6e642d3400000000000000000000000000000000000000000000000000000000000000",
+ "in3":{
+ "lastValidatorChange":0,
+ "lastNodeList":9187903,
+ "execTime":45,
+ "rpcTime":45,
+ "rpcCount":1,
+ "currentBlock":9201637,
+ "version":"2.1.0"
+ }
+ }
+ ]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_call_2.json b/dotnet/Test/Responses/eth_call_2.json
new file mode 100644
index 000000000..d422b256d
--- /dev/null
+++ b/dotnet/Test/Responses/eth_call_2.json
@@ -0,0 +1,53 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0x00000000000000000000000006012c8cf97bead5deae237070f9587f8e7a266d",
+ "id": 1,
+ "in3": {
+ "proof": {
+ "type": "callProof",
+ "block": "0xf9021aa00d4eaa6808c43eeb79b789b4134d87bd406fb8dc52f5f0d0ac54e12bbce66b28a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca03c98eea5b355fb0c78ee640a044dad450976e8dd91b99e2f54715f9fb480d5d2a0f3dba66e046da028e9b8c0e5a10cafd32af7aa0188f2cf7c367765a31b064a29a0f21cbc82667c6d4b44bb4237ac4efc9addd2795f97b17ca7f196f71f96f5f24ab90100ea8140021c33a889016d222158111b4730e04a90c1112ece198029409201ae61f40812f760384e06806081060b0047040fa904885b113889200b50d060faaa801508804882038212481c001dd0c01866a684a6280660f14cb640e0a5a240a29a1808150606c150a52411525c3aa538232208150078409c993808d036700030e42c20f1826301c413d02d8c15cb2685b3e4248d6d4f83503ce1d100c1741240c862d80501803607411aa068d505c48444302e8580d5804032286008061e253e075284064b6832447044c640321900d22548653603838082b1412252cac0906045b2907404008910a0e46a689dc51403018884002092a7525012640c8c98b121128707e3debd89ed3c83910c8c839896808398668c845e4b9ba1995050594520737061726b706f6f6c2d6574682d636e2d687a33a00678985580d2d23a46b06f737237ce0d1fe5858d9c21211ac33e7ebe2e41b9ba88885cf9e819a5e5b4",
+ "signatures": [],
+ "accounts": {
+ "0x1da022710df5002339274aadee8d58218e9d6ab5": {
+ "accountProof": [
+ "0xf90211a09c03df5c89a0e9395b562160851aba29135d62803bd66aed2bad92412569e24fa0bda2632214d8048a5d4c45c8d32fff36d8746aae3caf6fe1d0f1a5629b12951fa06ba04d3584e2c05a0957f683e2d5e5a121c1fdb005812a14aff3def670ff5ebda0d49464cdf2a4d4a1a0ba39b0d94df1d5c8be7321360f5b5a45e7d694ab609521a04526138afbb8fd8a39f70b3d177d63b36dd6f4ac0e070f64f35be80c993bac8ea0c1af85dfc243cdf8720ea926cc89c6918ca74357d1fdda8668dac8aeff4621aea076b7501be573cc64ad2334320754806c10b5fee2585fa897f3c261a9a64afdd3a0cf8a6027d1b375c597d1d6615b36b1145df8d325f93c38f49575d6e59a613860a06fd030173a8414b3cced39156003a52dc28ef3092ecd9a7eb8d8d71bcdda87f3a00a8c1bc19ac9adc3feb00469d50d35301b4a7a4e50a5aa59c577f7d6e027ab28a05da84b9cc88bfc8a7693fb563a8e347e5d8baa104a151e7e7f34b98feb6d0be7a085073e0d549219f34847f7b98e6e038dcf14bb3a1f3214efcf580d6d82a35d5ba080b3d97bf23497c32abf0f3e4b060b6fb8bcb26ae61acea4094c8afde18ae7aaa0fa844ff2e77f44f74a949da1616b671f70af7a5b4f503a1223e4af94530f102ba0e488a45d433be7a536c4e35cd1c05ce96cf2be1c7cab9603e320592c1b159efaa0c2085955a09d0d3e87088259d220b586b735f97c5eef2b05dd575d035415424180",
+ "0xf90211a04749a4c101bbb6dd01fb691a0ce6bf852ebfb90b077876bd0e37b2b5dcae2488a0f59a0b4206c45226304a2230bbb45833b505f816a8bc6012bed188bca541134fa061e000493a2aa696debef6e67bd0267ef3a1bcac04b2993902a7bc032f756ddea0c98ab4cbdca8060b60151369be7ef6350b0105ef7823f8fa27d1f913814d73eba036d76f4bebccf0e56a603caeb2200a90d7d49d6186c4288dd7a6a4ab24dde8c9a02aefe5b95f3388dcc22f4ce475c7045ee24e2d2c0caa5e66b61f65c03e8d5576a062c439e1b407ef94b8bc7e6239b9e9743b91e4bd5e78d151c9a119d4f5110d94a01c84b7ca510e5fdaeb5268fd8f7c999110f5e6b54e8480ae336849687fd813cba0e9acba582def1382482ccb45fda3469cc494422a92054a9c5106c29204b7c680a0ee2d20a8d7f3300f9982bb3bf97bf8001598a80087c98e40b764e3798f3ac2dfa04bfaf6aacbcb47c93b93322c2e7a7d2f670ed4bc62035973a1ecd338c626e0d6a0d4f72511e88cb4020006ba6c0741c7ed4b78441f5e3ca27116dcc867281412d5a0465dac8345b7217b8696e06cb2eec8e258783b478c401272f05182bf3629e5b8a0c986ea622dc5f2d7a90c57e481cf999df06e6365671fbf8a01144b8c3f17fedaa0cc0c11adfe0b9b7574b32710b5aec91389b8023bfcef6e98d0da48ff1353a528a0c9c4f47d0a85762de16483edbcbf75482bdbb2e25f58ffa2a8905abb21cfb1a880",
+ "0xf90211a0421d47805960c9324c9c65cfaa2757cdef8d385d2d88aeaa918e0d629f7bee06a0bac3958ab28d8b3a47e3f74172bf276b0ca0ee061eb03e0799cf0982c5914ee6a02a7f71c1489c6ab83e4e5f637a016b67a2b439cd2098e9550feeadb1cc06b7b1a09ebccb005760d1e961c05222facc9edbd65279b09c9808dba610f9c93ee0162da03347dbb5ffc7953775b5c01025b00f6c475e9e91b2f333789d213c9eede988d1a0db1d1de6ea6a5abdfdca819f514799791e5901d27378bd7f5d24293be1f40f4fa001f094e4f1357189decdeca91c585f31373eb07cf3fd800e1ffac402b2422baba01a5a0fc0ae73e7eba87343c945baf0a39b78206e16b3110f6d4bca2bebe7956ca0d5138810079832b59c79ea1b1053862f77c9054b054ce26b88247da193d76751a029e6f99e90ddfd5bd3c0878d53d3d3863adfdb767fbd613be88f89926fc14149a049d9e1ac7b6ebd0921259c7f1762ee8bfeaa13920aff5b17cd8f9411a1404280a0294fcd70b9130d3fed293a5cb11f7cde367610531385fbef125242f801690fdda0f17e2d6c7ffdc496f1a0296f8f2879a77193e27882ba9db3f4bb10e1ce3f0fa1a0057b934f2cbbf29c5d19cbc450c1a620885c1cffe92a9790e349a9345a1ae5c0a04a8f7e0f98c6089ba4ae1f8f45d20effd66a1da08c31b94613eb4f285a0bc638a0d09b8c4f9920d6e7190bd3da780ea4ff91e47408703dc726c193b45b999c0a7580",
+ "0xf90211a0dd51143a61d6ea570b7bd5d0e5c9b7f12bac69808ade380be07167ef3d3ad70da0d540d6812bc7c09e6b6db29f1fc8d7751b2e3422fe002f410fb9ee382597fc10a0bd66c03133addce1cba3c8b9cc25c6144b510bd8ddd22b8880129a31417d0f77a019f8621ed8e0522b09db2f60294828fefebb07afb12f93156b66b6e4d39f10cba0da576600e4bfa9adebbd7bc039474e73178d00472caad4f5b94d28f263adce15a0b0a506bebb06ceab88d00df98204c3b01f1a5e0ddd6da1d00785bf197e56dcfea091f4ba55a9f7e78075a0e40a081e56021953109a3dc18169a1b889496ea5ead4a0c00e14ffbe2adcef450f3d68bf3c742981af27de1e7afd303bd8c002b307dcaca04235436790dba10839f6b92dc0e9d9a7d8dc56ed16b565fc9628d98f99318063a076c019b378b1d7a75b1f0d5bef8dfe5d37578ba017b4be2691810d4108b97abaa0ba85578eca7cf82f89d89cd13fa9fd4c3dbdae1d337a8bddc76cffe6c235f6cfa0fc83aa4c3b5d32f565137173691efa74aed1054aec6a2a23d0f007cde3528183a0fc893b0b296ae92da4edfa3ecc59610871bc84cce95bb71f185614e1e70af859a09980836c7b1d74b244335d2f5039882fb0cfbcc7c19cd82e5277ef6c0a76367fa0a079297c4f6e850a5f3bdfcefb3553141ed41b66fab93fb3210af673ede2d248a00e3098f23c3a91de30039eae480bb8bdab723a49a9cab8cb50817f391a97dcc680",
+ "0xf90211a0c1b92c857da0340b0ce443833b66e5d0314ffd1cf92f2d695734456724e375eba00edd53ca526fd6f0ec43ea34ac4615f6997f5b1c0816f43794359b73f1ffc1c4a03e3c016f181362c3061a2f10b7d4aa4bc33c8d843a0ae464f3f2a96c153c437aa075c74847eee27cbf4f2031f76ad5f81d15646dd166f92e014529fd588e55ecaea06e2d4692022e8518a3017e4ce614264d592a2e5bc9ab4eafd274550dd962a63ea005d2e402784d5d1ccd4f63effb9d6f3fc955607532976656b344fbc2f6254d61a050d0b371e5324fe1753f81c8b0099b4426cc71e61025b9dc4acbf97ee91269cca04a733100cb3ff46ca6801d8ef5c4a5c17ef841efeeb0145cf49090c40e5d1580a09f5d83f3f0d0f697ca29c1b2d73800f19e195965215d4def53615435c73b4229a0013dffcd30a1233cf6dea6f8890557f925f303a89999faf2229ee6e1b51fb928a0f9e4d06cab2e49c9a2c8b88e5e4e2ca1266284cfa30a75a257ee1dd6994824ffa0f7f003ea25289eccff8b34fc78f3e821d557e6e0b93260b7eebb14a8ca069b06a037c82c23d927730ca6d4eaec8e3f2c188dceba6b99db4fc1bdb5b97fcc642af1a0804b978d2965c4913aeb43ac4eb2e8eb7136b6f275c37977203522cf1fa0ed34a04bd08b3b746253d0e5dfced158ccc7babccc8f3f862a033aa0efadae7775e070a0ca301518f7fcfdd10e24ae77d03f57ba1362bccf9d91f4ea3eeb54cd8588ee1080",
+ "0xf90211a094ff7643ea6a0875424d4bc0e7da632ee374cf92b23331dd200af20ab5108cdba02fdde91dfe1c91fcad765379bd602c17c488f0d0e65ec1cfddc45f89ce202213a0581479dd203d8a5d727c9eab7c3f95ed8dfd22c901c79d171dfb3f62a65cab55a06bafdd88fd4ca1d1019e0ae925fd55e93a12b8e90e395d4ff8f98584ae852c33a06d855744c75ccfdd9fbf5c6936d5382d1d31d8fce311e2d2d4c60c402b34c0a1a08b79b80a00b9b028748bd6b7d7bb0ab27502c7f6546705f8e67505a808fc6ba5a0fbb00de89d433d33dfad3a0cb5ffede3dfc41a97901a2b4730df6e82b04e575ea07f11477d71bc9ef74a721d3b94f46459ffb7bb16b1bdf420515dce624ebcc78da0a095d4c285e725c5e7ff550ebd4816b5cc89690f69ec9482a5bb65445bc685eca03958da0619d48a296def1741501057ca9383644839ca6dbb8e1089b3ee26b240a0cd32aa41e090d9c1eb92d6cf897ae1d0726d90525840044569d1c26ee00543cfa0a23d881cb739ec54c5428a212699c76649a64f46652252cc423935688e0b02a2a04749a577db36c04163e0bce5dfe0c7ffd76c6611c6c107379d57a45cbefc1ef9a0d3f2980a7f16010f56dab3b27234d5bb313ff34e86e56af270beb6b57dfa8c20a002a477a48013182250b9dd2ff85f508603920b13cef7b493e7282ae238e2bf11a0ac2d7c401dc1439cd0d1cfe8cf1c218144e261f35bda1c66d23cb36dc3ef71ac80",
+ "0xf8d180a08a5f70d31b16fcc2c06b558972d8c8cfebb63ecc7b45565eef21e8ed2191a51f808080a0674b12ef5b6b2104a014ceccba26c17b0ced72334b64aaeb53085ab4ab799188a0fb66681fdfb84951238da74372bfa7ca780cb48ee1d2b3dec484b5074fddd46f8080808080a01e1480859e14558b1a689d138a5e931e3270fdc7065b584a7fab17ed77f29926a0ea1989c7493a30d5a9a2dea74c5526e3922a94e3a8f33e2d335244a7dd43e8c0a00b08a289e59e8e38f42b21291a3c91861e0e94266000a8099f6302d9460015f88080",
+ "0xf8669d37ecef1dd7ed16827708f440d9beccf60a5ac8af5646f28db424c8ae7cb846f8440180a0cab2b579fa27d8d21dfa82076a7782c03745a97da929ede1b2a31eacd855e874a0ca1658c2e5516c4bc959e682d9a4cf235e8c28b5eef98aaf7ded27142689853a"
+ ],
+ "address": "0x1da022710df5002339274aadee8d58218e9d6ab5",
+ "balance": "0x0",
+ "codeHash": "0xca1658c2e5516c4bc959e682d9a4cf235e8c28b5eef98aaf7ded27142689853a",
+ "nonce": "0x1",
+ "storageHash": "0xcab2b579fa27d8d21dfa82076a7782c03745a97da929ede1b2a31eacd855e874",
+ "storageProof": [
+ {
+ "key": "0xc848fdf77cc0f2f355981619cea0e9d55c2399f1f5afdd4494a1e62363e47c0d",
+ "proof": [
+ "0xf90211a0467c60cdf034065efdfd22ceb8458ffab017343c2444558d6d97605fc0702f68a05796d8d7d3967ad64900143a234199008e96efc6c2d3adcdf34d1689a2b1531ba040a1c802995378db6ed34e824d31df278e83d5b0718718743770975ef42b2bcda0680f0ed73a4544acb3fc39f63610eef68e0b99d58cbfb8cbe932451d7d2dc082a07986f67b7a0c2afe4ad55d2b52db859265ee1bc023fb73334ee508064155c997a02af0b5ea3c0acad20667243eeab67828a2faeccd964ac8921244fe73b180c068a02b1f850aecf2caff1fdf9bed8e2170408d8566ba9c0ad906a09bdab057568a9fa0134bcb4c9747c128c8ac698fa13023eccf8df06b15a6567019b63774117a28bfa0a1f95734cbb2ebc4690b580b80c7d775c1de50ca04e209a2b9e4ab193c9d425ba0dadf861a4b28231a3a7557128a0b256e32ae2d99b5040bb60fc794f9f86fc564a09d3f3d5924ab998736b246bd7dc848e170542ec00a1ee3a606057ac7a002ba29a0259b4bb16b712ceeba9e8b6153a91e33b65bbd177a704c4973d965eaa34cbb64a03cdc6113f74aee3e5e258ec7237ee5115a092ed701d10e913df8c3924e01eb76a0a593663dd92a2241ec7e8f692e92b418509dc623f38520b91e67b68396bdec11a0e1e260bf2757d472839cb4ebfc646e0ff4b8b7041a1a324c7fd355d3d7559bbda052e26ad2527bedda7414214992cdd25ffb9cea2e027c49712b9f007b8fc2272f80",
+ "0xf90211a011437e06aad067b401c100ef508fd2111a02b630b8e5a4c52c88dfc41c48ee27a03e729e2eb56f2b0630243f520765460cfe633c395aa64bed450b089be4ebed1ea043d9aade3132c903c4aa299673dd05909cf0b78834543be0eb9319a9e756a57da060963ddadddc3852d910ecb676992517f4442d0d2e3052b4fa05e01c85b99edba0649b73780dab5ef7384951a31f8ecf10e8add8aaff21f64d810deda754c5b926a018747924feba26ef7196e7eb54b900a98e23cc1ef7acc156234b902fd1e8d086a0fa5ccd5d57adf588f9ca86a6b73ab17632d983c9927225c2853730a6fdf84c3aa03faea24e91769ba46e2a201959f4f4ae350203721eac31e8d0ef3915aacf1982a0a43e7600ac427d7910305b04946ebd6d15fb9a90f3b1cd891cc66b3f12bed34aa04cd3ab22240af89561b7063301fe4a3caba69c303784a0cbe7c3fbafdb14085aa02a207f51a5479db4a461c0c564e87822cf70d0e7eef6338961a6936bc1bdfaa1a05ed1731052dafbbda71dfdebc534f17c07bd95882430356ff276e0c1465607dfa07b68c0e1d39b467c0000b917a954f800c945329dda403e72cf6427a9e09d6aaaa0df5a7dd22ac55108e0d9f87cb022d334360f9471472090993cfef9156adf7dc8a0017d74f963cb610f8448c68fab87c45450f0b47d30094760a8b7d47014b2419aa07caaa80bff6d5fc7895e69d8573f784758dbf3da2f6bb4f2cd9459c01afffa2180",
+ "0xf90211a0950ace6b297c31ad3477c5bde5f156e2b639f5f1460ff6c8f643789b751b9da6a009c0cafe2f8e796bb8d23598732fab880710ff30dcc60a14c6ce3f872bfd1033a0f37814e343f287b5ae49f8d60a7f084be328ab3ad9b934bf4b8a192ca8828d5aa0624b3440eac4ba121953009bb6c6a70eed748bd17d3734b19b7b90d7f3b2b2dfa075ca7a41bf2f4e44cc09f0fefb275c17755f67c5d887f64e0bda048739f6eeb1a0db8a3e8eb8672fefcfcecd32ff86449e923ce5b7b62a3a50a88a365835eee90da028f5fc4d8ffafd78828e7ba6440f4ebcc917019a7b5fe1874c1374c89a7ff9b9a0fc4a0836a34b7f0ee1c3309a33b7228f533be2edd8a578eab2c875cf3f90c546a02c9fbba1878abc494c671ce475ea32fe237092d68eb93ba8a6d33f7aa76efbe4a0d0f1d867d11509fd1e9388ba3a293b3369a32d4fab841b53d141d971a6725438a0e05ffc695903166cb488f6f96e1b989cd16c4c03c1a3629f18a14c68143aa226a0975837d2f5dec549a1c5250e524de4113604ca53f9f65c9d51b9192c9fbecca4a0f672d7e3ddb6de3b2d81af90363c4bb30bee173b2d8e806b43f652871dc9f31fa065ac71a82f8d0464641c812bcadcd5d959124e740c33856893dad9a7f819c195a0dd6b9e04f7dbbf5b33fba2df751b07db33342d70e8b630e05fb48ecb03b6cfefa0df17ec6efa3ced8a815626baf8d9660af9cdf9f71eb45d8f6665d8e0c28b461680",
+ "0xf87180808080a0b0307376726efdec4f3f654675216698e2ce7ccfa717bdcd37be56f4080762f0808080a064c62ea1a1cfdeb8c6312c988d30ceca56274e86e1a14603c8cc1dd9951bf52f80a066d6d805d6ece8f57e7b7efedd9a8afb46c6bc88c510d360b57133caa86d4a39808080808080",
+ "0xf69f20418c51730f6a5ce35c0dbc36fb093e8f537e867199f58ce93429fab67575959406012c8cf97bead5deae237070f9587f8e7a266d"
+ ],
+ "value": "0x6012c8cf97bead5deae237070f9587f8e7a266d"
+ }
+ ]
+ }
+ }
+ },
+ "version": "2.1.0",
+ "currentBlock": 9505932,
+ "lastValidatorChange": 0,
+ "lastNodeList": 9491715,
+ "execTime": 21,
+ "rpcTime": 18,
+ "rpcCount": 2
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_estimateGas.json b/dotnet/Test/Responses/eth_estimateGas.json
new file mode 100644
index 000000000..afcdfc99f
--- /dev/null
+++ b/dotnet/Test/Responses/eth_estimateGas.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x5208",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9298988,
+ "execTime": 55,
+ "rpcTime": 55,
+ "rpcCount": 1,
+ "currentBlock": 9299061,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_gasPrice.json b/dotnet/Test/Responses/eth_gasPrice.json
new file mode 100644
index 000000000..0fab54243
--- /dev/null
+++ b/dotnet/Test/Responses/eth_gasPrice.json
@@ -0,0 +1,5 @@
+[{
+ "jsonrpc":"2.0",
+ "result":"0x7d2b7500",
+ "id":1
+}]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBalance.json b/dotnet/Test/Responses/eth_getBalance.json
new file mode 100644
index 000000000..bbe1822c5
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBalance.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x329a1e26bab74000",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9278788,
+ "execTime": 95,
+ "rpcTime": 94,
+ "rpcCount": 1,
+ "currentBlock": 9278893,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBlockByHash.json b/dotnet/Test/Responses/eth_getBlockByHash.json
new file mode 100644
index 000000000..2834c18b3
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBlockByHash.json
@@ -0,0 +1,37 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "difficulty": "0x400000000",
+ "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
+ "gasLimit": "0x1388",
+ "gasUsed": "0x0",
+ "hash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000042",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x21c",
+ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x400000000",
+ "transactions": [],
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncles": []
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9285819,
+ "execTime": 109,
+ "rpcTime": 109,
+ "rpcCount": 1,
+ "currentBlock": 9292674,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBlockByNumber.json b/dotnet/Test/Responses/eth_getBlockByNumber.json
new file mode 100644
index 000000000..2834c18b3
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBlockByNumber.json
@@ -0,0 +1,37 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "difficulty": "0x400000000",
+ "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
+ "gasLimit": "0x1388",
+ "gasUsed": "0x0",
+ "hash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000042",
+ "number": "0x0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x21c",
+ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544",
+ "timestamp": "0x0",
+ "totalDifficulty": "0x400000000",
+ "transactions": [],
+ "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "uncles": []
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9285819,
+ "execTime": 109,
+ "rpcTime": 109,
+ "rpcCount": 1,
+ "currentBlock": 9292674,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBlockByNumber_1.json b/dotnet/Test/Responses/eth_getBlockByNumber_1.json
new file mode 100644
index 000000000..548c3eac5
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBlockByNumber_1.json
@@ -0,0 +1,42 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": {
+ "author": "0x0000000000000000000000000000000000000000",
+ "difficulty": "0x2",
+ "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000cb9334ee9f7a081bab4bbb50e2ec2c0a77a529c8ac905abc760df828d635c1872d6bd784df10ef485fde3acdd38e62e5ffa8426fca6767627f8fde612291a9e900",
+ "gasLimit": "0x7a1200",
+ "gasUsed": "0xaa03",
+ "hash": "0x03b1815a066ba71eab8e6622afa3e596b80580c2b1056990199dd974db66337e",
+ "logsBloom": "0x00000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000001000000000400000000000000000000000000000000000000008000000000000800000000000000000000000000000008000020000000000000000000800000000000000000000000010000000000020008000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000100000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "number": "0x1f5c2b",
+ "parentHash": "0xfb66516f17f13339edc2a4ab6929f75669a1b3b7ed200e862338d0b2c63e36b2",
+ "receiptsRoot": "0xd815138f1ba5d2dc76817c529d4c637328af0080ad28a91c241e38fbaf062811",
+ "sealFields": [
+ "0xa00000000000000000000000000000000000000000000000000000000000000000",
+ "0x880000000000000000"
+ ],
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x392",
+ "stateRoot": "0x30ce3fce6d7f2451c7c86afe85c85bc0ab72d8ea827ec74930f26ccc70d57d9a",
+ "timestamp": "0x5e2ab82b",
+ "totalDifficulty": "0x2f2ca7",
+ "transactions": [
+ "0x27df49d655f3bd520de497de83bd96d5f271ea733de9f5e273494977beffa1d8"
+ ],
+ "transactionsRoot": "0xc697a33f23bf8a176ff43cfbc0cea1c5c43f93c813da5b564cd40883dea6e01c",
+ "uncles": []
+ },
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 49,
+ "rpcTime": 47,
+ "rpcCount": 1,
+ "currentBlock": 2055213,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBlockTransactionCountByHash.json b/dotnet/Test/Responses/eth_getBlockTransactionCountByHash.json
new file mode 100644
index 000000000..6e0cb0720
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBlockTransactionCountByHash.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x0",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9298988,
+ "execTime": 69,
+ "rpcTime": 68,
+ "rpcCount": 1,
+ "currentBlock": 9299412,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getBlockTransactionCountByNumber.json b/dotnet/Test/Responses/eth_getBlockTransactionCountByNumber.json
new file mode 100644
index 000000000..39194ca70
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getBlockTransactionCountByNumber.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x79",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9298988,
+ "execTime": 4785,
+ "rpcTime": 4784,
+ "rpcCount": 1,
+ "currentBlock": 9299437,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getCode.json b/dotnet/Test/Responses/eth_getCode.json
new file mode 100644
index 000000000..bc601dbe4
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getCode.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x606060405260043610610196576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461019b5780630753c30c14610229578063095ea7b3146102625780630e136b19146102a45780630ecb93c0146102d157806318160ddd1461030a57806323b872dd1461033357806326976e3f1461039457806327e235e3146103e9578063313ce56714610436578063353907141461045f5780633eaaf86b146104885780633f4ba83a146104b157806359bf1abe146104c65780635c658165146105175780635c975abb1461058357806370a08231146105b05780638456cb59146105fd578063893d20e8146106125780638da5cb5b1461066757806395d89b41146106bc578063a9059cbb1461074a578063c0324c771461078c578063cc872b66146107b8578063db006a75146107db578063dd62ed3e146107fe578063dd644f721461086a578063e47d606014610893578063e4997dc5146108e4578063e5b5019a1461091d578063f2fde38b14610946578063f3bdc2281461097f575b600080fd5b34156101a657600080fd5b6101ae6109b8565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ee5780820151818401526020810190506101d3565b50505050905090810190601f16801561021b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561023457600080fd5b610260600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a56565b005b341561026d57600080fd5b6102a2600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610b73565b005b34156102af57600080fd5b6102b7610cc1565b604051808215151515815260200191505060405180910390f35b34156102dc57600080fd5b610308600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610cd4565b005b341561031557600080fd5b61031d610ded565b6040518082815260200191505060405180910390f35b341561033e57600080fd5b610392600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610ebd565b005b341561039f57600080fd5b6103a761109d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156103f457600080fd5b610420600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506110c3565b6040518082815260200191505060405180910390f35b341561044157600080fd5b6104496110db565b6040518082815260200191505060405180910390f35b341561046a57600080fd5b6104726110e1565b6040518082815260200191505060405180910390f35b341561049357600080fd5b61049b6110e7565b6040518082815260200191505060405180910390f35b34156104bc57600080fd5b6104c46110ed565b005b34156104d157600080fd5b6104fd600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506111ab565b604051808215151515815260200191505060405180910390f35b341561052257600080fd5b61056d600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611201565b6040518082815260200191505060405180910390f35b341561058e57600080fd5b610596611226565b604051808215151515815260200191505060405180910390f35b34156105bb57600080fd5b6105e7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611239565b6040518082815260200191505060405180910390f35b341561060857600080fd5b610610611348565b005b341561061d57600080fd5b610625611408565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561067257600080fd5b61067a611431565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156106c757600080fd5b6106cf611456565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561070f5780820151818401526020810190506106f4565b50505050905090810190601f16801561073c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561075557600080fd5b61078a600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506114f4565b005b341561079757600080fd5b6107b6600480803590602001909190803590602001909190505061169e565b005b34156107c357600080fd5b6107d96004808035906020019091905050611783565b005b34156107e657600080fd5b6107fc600480803590602001909190505061197a565b005b341561080957600080fd5b610854600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611b0d565b6040518082815260200191505060405180910390f35b341561087557600080fd5b61087d611c52565b6040518082815260200191505060405180910390f35b341561089e57600080fd5b6108ca600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c58565b604051808215151515815260200191505060405180910390f35b34156108ef57600080fd5b61091b600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611c78565b005b341561092857600080fd5b610930611d91565b6040518082815260200191505060405180910390f35b341561095157600080fd5b61097d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611db5565b005b341561098a57600080fd5b6109b6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611e8a565b005b60078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a4e5780601f10610a2357610100808354040283529160200191610a4e565b820191906000526020600020905b815481529060010190602001808311610a3157829003601f168201915b505050505081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ab157600080fd5b6001600a60146101000a81548160ff02191690831515021790555080600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fcc358699805e9a8b7f77b522628c7cb9abd07d9efb86b6fb616af1609036a99e81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b604060048101600036905010151515610b8b57600080fd5b600a60149054906101000a900460ff1615610cb157600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663aee92d333385856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b1515610c9857600080fd5b6102c65a03f11515610ca957600080fd5b505050610cbc565b610cbb838361200e565b5b505050565b600a60149054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610d2f57600080fd5b6001600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507f42e160154868087d6bfdc0ca23d96a1c1cfa32f1b72ba9ba27b69b98a0d819dc81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615610eb457600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6000604051602001526040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1515610e9257600080fd5b6102c65a03f11515610ea357600080fd5b505050604051805190509050610eba565b60015490505b90565b600060149054906101000a900460ff16151515610ed957600080fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610f3257600080fd5b600a60149054906101000a900460ff161561108c57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638b477adb338585856040518563ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001945050505050600060405180830381600087803b151561107357600080fd5b6102c65a03f1151561108457600080fd5b505050611098565b6110978383836121ab565b5b505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026020528060005260406000206000915090505481565b60095481565b60045481565b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561114857600080fd5b600060149054906101000a900460ff16151561116357600080fd5b60008060146101000a81548160ff0219169083151502179055507f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6005602052816000526040600020602052806000526040600020600091509150505481565b600060149054906101000a900460ff1681565b6000600a60149054906101000a900460ff161561133757600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231836000604051602001526040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b151561131557600080fd5b6102c65a03f1151561132657600080fd5b505050604051805190509050611343565b61134082612652565b90505b919050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156113a357600080fd5b600060149054906101000a900460ff161515156113bf57600080fd5b6001600060146101000a81548160ff0219169083151502179055507f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60088054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156114ec5780601f106114c1576101008083540402835291602001916114ec565b820191906000526020600020905b8154815290600101906020018083116114cf57829003601f168201915b505050505081565b600060149054906101000a900460ff1615151561151057600080fd5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151561156957600080fd5b600a60149054906101000a900460ff161561168f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e18980a3384846040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b151561167657600080fd5b6102c65a03f1151561168757600080fd5b50505061169a565b611699828261269b565b5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156116f957600080fd5b60148210151561170857600080fd5b60328110151561171757600080fd5b81600381905550611736600954600a0a82612a0390919063ffffffff16565b6004819055507fb044a1e409eac5c48e5af22d4af52670dd1a99059537a78b31b48c6500a6354e600354600454604051808381526020018281526020019250505060405180910390a15050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156117de57600080fd5b60015481600154011115156117f257600080fd5b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115156118c257600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550806001600082825401925050819055507fcb8241adb0c3fdb35b70c24ce35c5eb0c17af7431c99f827d44a445ca624176a816040518082815260200191505060405180910390a150565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156119d557600080fd5b80600154101515156119e657600080fd5b80600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515611a5557600080fd5b8060016000828254039250508190555080600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507f702d5967f45f6513a38ffc42d6ba9bf230bd40e8f53b16363c7eb4fd2deb9a44816040518082815260200191505060405180910390a150565b6000600a60149054906101000a900460ff1615611c3f57600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e84846000604051602001526040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b1515611c1d57600080fd5b6102c65a03f11515611c2e57600080fd5b505050604051805190509050611c4c565b611c498383612a3e565b90505b92915050565b60035481565b60066020528060005260406000206000915054906101000a900460ff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611cd357600080fd5b6000600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055507fd7e9ec6e6ecd65492dce6bf513cd6867560d49544421d0783ddf06e76c24470c81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611e1057600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141515611e8757806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611ee757600080fd5b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611f3f57600080fd5b611f4882611239565b90506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550806001600082825403925050819055507f61e6e66b0d6339b2980aecc6ccc0039736791f0ccde9ed512e789a7fbdd698c68282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050565b60406004810160003690501015151561202657600080fd5b600082141580156120b457506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b1515156120c057600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3505050565b60008060006060600481016000369050101515156121c857600080fd5b600560008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054935061227061271061226260035488612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156122825760045492505b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84101561233e576122bd8585612ae090919063ffffffff16565b600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6123518386612ae090919063ffffffff16565b91506123a585600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061243a82600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008311156125e4576124f983600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a350505050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000806040600481016000369050101515156126b657600080fd5b6126df6127106126d160035487612a0390919063ffffffff16565b612ac590919063ffffffff16565b92506004548311156126f15760045492505b6127048385612ae090919063ffffffff16565b915061275884600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ae090919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506127ed82600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000831115612997576128ac83600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612af990919063ffffffff16565b600260008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a35050505050565b6000806000841415612a185760009150612a37565b8284029050828482811515612a2957fe5b04141515612a3357fe5b8091505b5092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6000808284811515612ad357fe5b0490508091505092915050565b6000828211151515612aee57fe5b818303905092915050565b6000808284019050838110151515612b0d57fe5b80915050929150505600a165627a7a72305820645ee12d73db47fd78ba77fa1f824c3c8f9184061b3b10386beb4dc9236abb280029",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9278788,
+ "execTime": 200,
+ "rpcTime": 199,
+ "rpcCount": 1,
+ "currentBlock": 9278949,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getGasPrice.json b/dotnet/Test/Responses/eth_getGasPrice.json
new file mode 100644
index 000000000..f9563ea88
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getGasPrice.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x77359400",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9297851,
+ "execTime": 62,
+ "rpcTime": 61,
+ "rpcCount": 1,
+ "currentBlock": 9298237,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getLogs.json b/dotnet/Test/Responses/eth_getLogs.json
new file mode 100644
index 000000000..ae0b2e55c
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getLogs.json
@@ -0,0 +1,422 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000031826a1613470fc3d2eb794e93af7477ee8fe0ad",
+ "0x0000000000000000000000009e6adb80dd43d07df9f2f43f8434080c4528102f"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000000000000349d05c5c",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x20be6d27ed6a4c99c5dbeeb9081e114a9b400c52b80c4d10096c94ad7d3c1af6",
+ "transactionIndex": "0x25",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x24",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000d2349d84187580c73f1c77669f6f409dc425c3a3",
+ "0x00000000000000000000000006130d80f131e922ea300e8bc5c8e1a01c137bb3"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000001e65fb80",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x1e41b814b0e740c92590e1cf5bf0a6c21a27bdb7fb35b164d2ea72df05c8414a",
+ "transactionIndex": "0x33",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x32",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000d2349d84187580c73f1c77669f6f409dc425c3a3",
+ "0x00000000000000000000000081cd27dd424f3cb8befd91f248152a151c4e3421"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000000000000185f13d4c",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x9a92562c1c84fbea52332efe7fe2bc6e68ebadcc8958bcb9b85546077cb3f9b7",
+ "transactionIndex": "0x34",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x33",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000d2349d84187580c73f1c77669f6f409dc425c3a3",
+ "0x000000000000000000000000d0b4915192c62abbda9fcb6c4b97a3970868dc71"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000000130d877d",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x486b66a75e320b90ecb8a786f08bbbe7802faa8fbffb64ad0f192f5c9b88adf6",
+ "transactionIndex": "0x37",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x36",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000d2349d84187580c73f1c77669f6f409dc425c3a3",
+ "0x000000000000000000000000113b26e69adc3c77f1ae832e3df67507218bab4e"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000000fc439787",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xec5c8f5d004733d3ec56aa827b535a68e8a0dca18f07cc2dc55ebd561179135c",
+ "transactionIndex": "0x38",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x37",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000d16818441f154cf41323e18ff6dabd98f7d4d826",
+ "0x0000000000000000000000009e6adb80dd43d07df9f2f43f8434080c4528102f"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000005e9c1d8bb",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x9217c5fe8c730d27a7fb0055628f229f48aca19b9a3d858f290c01b7084de978",
+ "transactionIndex": "0x3a",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x38",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000c7dc5c95728d9ca387239af0a49b7bce8927d309",
+ "0x00000000000000000000000074dd0407a0213c4b96e991dc6422d4e0f44e22e6"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000003b3f3c80",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x21857b088788c302dfef62a816222b668a3eb17427b5267e48328606fbfa8240",
+ "transactionIndex": "0x3f",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x3a",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000c7dc5c95728d9ca387239af0a49b7bce8927d309",
+ "0x000000000000000000000000a373bb7c9ac1d05bf0fe77bafb22b4b6dff16b62"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000007650b240",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xcc315874a5727024c9608596cd8614cd95e07e8285377d3d7dee848a9206de52",
+ "transactionIndex": "0x40",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x3b",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000075e89d5979e4f6fba9f97c104c2f0afb3f1dcb88",
+ "0x0000000000000000000000005e1f5a90cc266ede19522caac2c920d4ef6c75d1"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000000000000007270e00",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x9fb8d37680768997e8df27584230e1c29bee3d9d5b8bfbbec43488ebe97f34b3",
+ "transactionIndex": "0x47",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x47",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000008485d941f15e4d00ae871aaf568dfb6365dc8c3",
+ "0x000000000000000000000000c18f925b822f7c053794b63963affcfcb48d9219"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000000207c0a40",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xa091b49ad78350185abff3cbd50baf3cfc7de7546b2188a13ca101f4b4444ade",
+ "transactionIndex": "0x4c",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x4d",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000567593a88428bdadfa911d73e0663217debf6618",
+ "0x000000000000000000000000c18f925b822f7c053794b63963affcfcb48d9219"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000000429980a8",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x68770d3864f39e8466edfc3ff403180a58200781e9b0c4f4d41c187d466b79bb",
+ "transactionIndex": "0x4d",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x4e",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000b2ea04bca24fbe91fe5dcf2f9b3dc50fad582460",
+ "0x000000000000000000000000c18f925b822f7c053794b63963affcfcb48d9219"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000001ec93332",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xcfa152e15a5ad540271a10d04b0a3355a6d688fdadedd64f388b9fc8b85a6291",
+ "transactionIndex": "0x4f",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x50",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000083d6454ccec07867de02abd89b0c87182e413dc6",
+ "0x00000000000000000000000002dcf837998b16f5fb11dadb0fca73fc340c03d3"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000604ae67",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x7b50a6044bb4af938ed7c8eebea38b863b15c5b0b4524660f0366a44b5e86572",
+ "transactionIndex": "0x50",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x51",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x0000000000000000000000000c093b72627feb125913d078fabb1abd2eba92a5",
+ "0x0000000000000000000000009a3a5f023ef348cf11a9713df4c88ddd8b9d953a"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000003b8b87c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xbe9315fc868af430cfcd00e5669d4f4fea781021e7fa7b8a2af151246f0a78ed",
+ "transactionIndex": "0x59",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x55",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000027a18e185e1eac1e1f67759dcb7976fa3505bcbd",
+ "0x0000000000000000000000009a3a5f023ef348cf11a9713df4c88ddd8b9d953a"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000003b8b87c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x07d6055f19170cd8de3feb7f4f17bc14fe8070f6019681057429952b30e6d84b",
+ "transactionIndex": "0x5a",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x56",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000b112652dc526510a8eb18b2dbad28d04f53fcf91",
+ "0x00000000000000000000000079bde1b9af26b2d8be8f9af02376c84f11edce09"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000000000001748492140",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xa2454a780b960e6279125a635c06c7f8a41acb3fff30750458364fa056a7ba2c",
+ "transactionIndex": "0x60",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x5d",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000b112652dc526510a8eb18b2dbad28d04f53fcf91",
+ "0x00000000000000000000000079bde1b9af26b2d8be8f9af02376c84f11edce09"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000054f6733c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x4e8e48086e93ce75a9426f74e00e48c3f52ef319e1857f37a6855bf401e8a7b4",
+ "transactionIndex": "0x61",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x5e",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000f04da626a0bf80b2076588ede3a7ef46eaf0a08e",
+ "0x0000000000000000000000009a3a5f023ef348cf11a9713df4c88ddd8b9d953a"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000003b8b87c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xc82a3381331184f0882bc631e0415b7fcf40f4fc0baaa506cff621a237f3c714",
+ "transactionIndex": "0x62",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x5f",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000fa894720503bf50410d1142f04f014b00ce76519",
+ "0x000000000000000000000000ce7307702c54b9c9c8779a5a7d7aa331e7dc2746"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000001da0c984",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x13c077890ca61697de1ebf44619500ecc0e1f652e692ae126b628946cbb32751",
+ "transactionIndex": "0x6d",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x66",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000fa894720503bf50410d1142f04f014b00ce76519",
+ "0x0000000000000000000000003c80bccd0e0704281b17f1760f3809f814e68966"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000000115fefe0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xa0600449aab35936a34485bec2ac64c0ee3c5678a38966ef2a0afe2a7de88dac",
+ "transactionIndex": "0x6e",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x67",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000fa894720503bf50410d1142f04f014b00ce76519",
+ "0x000000000000000000000000f5c67decbf0c08f4f114abe85743f06680ff9242"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000206cc80",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xf00abd79d4e95985fb736a6473361b72de38342672d39e82a36ff1ec1fb288f3",
+ "transactionIndex": "0x6f",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x68",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000fa894720503bf50410d1142f04f014b00ce76519",
+ "0x0000000000000000000000009b3d7ad0b1e9bfc221974c2ef6ef71b5ce00de2d"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000001a13b8600",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x6763e1d18a92f70f7168e34b90308e72b41ca55b62a1de3beab40c15509decbf",
+ "transactionIndex": "0x70",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x69",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
+ "0x0000000000000000000000004dedb21773975a8eb4cb308b7329e01e48239d8d",
+ "0x0000000000000000000000003116aa3a0721cfe9e61030f5f905b5566155080c"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000005315cc5c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x1e8179611f934189add9b0e7ca67126a89a7153b8e7f7d9c273e4423221effa4",
+ "transactionIndex": "0x73",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x6b",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x0000000000000000000000004dedb21773975a8eb4cb308b7329e01e48239d8d",
+ "0x0000000000000000000000003116aa3a0721cfe9e61030f5f905b5566155080c"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000000005315cc5c0",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x9291559799ba5d9ca708ec9624314ce8cb780cae107c6b5ab5c99d4ce39e8177",
+ "transactionIndex": "0x74",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x6c",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x000000000000000000000000fc2356d11875e473a8dff6f2f3887be7914d2640",
+ "0x00000000000000000000000051e98183410034572ce170dba5bfc72152a86c8d"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000003b9aca00",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0xfa8d72e80d5f8f93600853b98205bcbbf1825c7fc6b6d61f3a60449cf3f1ce09",
+ "transactionIndex": "0x7e",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0x72",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x00000000000000000000000005d923b938d70f783c0980b66279a146010aae76",
+ "0x0000000000000000000000005b2c26fe961b6e451b0da506d98fc007f79e1f53"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000c8b3650",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x58e57aef4840bc7c5505fd8aed099b05f0db3ca27d13ae14eabf0d9ea121376f",
+ "transactionIndex": "0x8b",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0xbe",
+ "removed": false
+ },
+ {
+ "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x0000000000000000000000005644e5d2c95c96cf5650989c57c0357c02d7a3a8",
+ "0x00000000000000000000000094f736dbb46f25d248f9dcc1f24bee38e8e4eb4e"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000460c210",
+ "blockNumber": "0x834b77",
+ "transactionHash": "0x7073e2f7a4e0ad3aa8198b1a80427a9a776b0559fe6593570963bfd700a85e40",
+ "transactionIndex": "0x8c",
+ "blockHash": "0xcc66dc39266f60a86380bf2df8263e24818bd33e6ffffd7002a4b2d73b37efdc",
+ "logIndex": "0xbf",
+ "removed": false
+ }
+ ],
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9278114,
+ "execTime": 178,
+ "rpcTime": 178,
+ "rpcCount": 1,
+ "currentBlock": 9278480,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getLogs_1.json b/dotnet/Test/Responses/eth_getLogs_1.json
new file mode 100644
index 000000000..ea2c57323
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getLogs_1.json
@@ -0,0 +1,110 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": [
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0x1296c7d85d1e4ede96d795c83a23119d6c30cdeb0da8097c0719a25fdc2d61c1",
+ "blockNumber": "0x1f4927",
+ "data": "0xcc09b2a08a988809c2389e417ff287ed608b1b1064a593c0fdf829300f4d664e00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000002d47373682d727361204141414142334e7a61433179633245414141414441514142414141434151444d3854567a67326b6c2f35567850486a706d6b5952577a347a37565939505262667365496f7a39553270596235377168314777776147454a4758557255446258386362515259417a4d38642f4e495951386631303531495056422f3173396e4f494c624748756375344c665349576b462b59325368685a32676a6a7731743669513048344a336569495638454c57312b41504259414966727244372f50434f316d74634439322f427059304c3244625677394963644b43533141347667694e6a68482f76734d34307338584f446e66484142686d4f5461676152786f414a304f4e504b412f5737543436596c4c4b2f5832374659486c7a4e364b4d696a763153556859462f55336871355248617846427a38586e726b543646672f5235432f6d706849596c686e33456e473849384d6c466863315569777a765230364b5958564138556459634a4533327670586b664c414e416e444974456859495362424e56566e4c57456c2f496f686b7136627975353841476b5673493248566975746b4c6b6a6370454c65574d584a7430315174786438722b3634433037527232373774654e696939706d34344868476759657a353157474b4d524c68534435422b6b55734d6a564e3732455633684657754d4f44442f514c585565515062323655376530383755714d5735536e2b4e414866385838725362385251506633506e725a6a506f735961596f7873675141354e6a536b664467535046347646314d597455524568424f6146454d744f75697a595470726f6d2b79317978674f5946732b35564f77316e65456655656b4b426b4e7678555a6a2f4f36324270356a577450687734523975466e7947393270486d4a537043416a3667386f4433714c514d566e4b485951684951334e4b374c62705a466d683347614466725030597439496b71697839456d54306b507631513d3d00000000000000000000000000000000000000000000000000000000000000095b372c20312c20315d",
+ "logIndex": "0x2",
+ "removed": false,
+ "topics": [
+ "0xb0ea96c9bd0971b86af31861a476f136b65848a43bc0e9df67995a1a3ef2d972"
+ ],
+ "transactionHash": "0xa70ae89f824a4e5d185dd447fa8a32b6ab38c9f5bbe92bfcee778babc5c1c67c",
+ "transactionIndex": "0x4",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ },
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0x9a5166e4e83eb7fb209b55f967130f6827d3dbd3beba765d2c3fc71bfcaee623",
+ "blockNumber": "0x1f492c",
+ "data": "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001f49450000000000000000000000000000000000000000000000000000000000000c245b224d55434f36474f487353665071557955747076796c6a6156516b48543777616e43444f4a4f4c5a3978317969576755496c703458416d4c6d7a746e5264364d4b416f70644c516b477a4e5370527a4c7a4d734f726c772b7279634944566d4764534568344447302f327055596e534c77694c4c6a63726956324750596670314e76634f41726431556f4763767956746a356d4241637242636b52776e51447744366479344f7969744851683234317876504c52724b74496a7270766c387831794e5441464f2b376352796b79336d6a43526569716534464848526b385379306a52415555387062474a504436536c614c7a6e4139364c727a66326366757a4430684332314e304e63445274794e62374b455863367047652b48714e4145436f69563073486863785574484e545a6f74335665563876556f376d4555512b556d696c446b58684e336e377964593373716a4b54686d704c6e58726b437844565642435a3638756c474868734b69465346675a2f346c522b574f424b5a6e627a6c53734b356a345875437779584d594b4d384e43704233626a73685576347a6b30447a515a794b57503371687831623847303146473969544a6e4b374970476d7354364c646839796e364d2b46507442315a79356e582b4479456b5164504c37636c6b6a595557686e66333745326c624b332f536f6157486a544c4e42654133794c726a6d384256367a552f322f30544d66516f5132654f677733617152456636483146484f315053704330716331556866374d6f485a4d6b4553534573664e476b6d65444673564b5539674b704f7077797933314f2f544e373956424e39334752734d4e6854567979514d476977477678386a52464542415242552f54485148504836486d79442b42716c412b516250425a59513479787454566447652f595136616f34776572566e6539553d222c20224755446e56664a7a524353474553315255556e3175673d3d222c202241647659704b50755641766b386d39423442554b757732436c6d51354a4e4b415962426546326646537566673151724555596d5265664c746e44524b316c79707a6c344f78796732716e68504f7968322f472f785677384f36344a4475584b7730616a6b595738654c4d62496e7155725147312b61563046527a58653771557930566c434c6d5674754577524e6e3173365774316b676a524d35793332654464492b713356776f6e502b43706b632b704f2b7a534356643874322f69733872567568475a6963592f3930736c5555644f466449474c596354743732387236753050535274393961663671697435627a377749322b6b7435306c644a656d714e73705170346f4e34336373617845304e7a646962306358334b3258644d676e5346576b334e4d6f336741304c33374b5236326b687351324347324b7153416c6e57793834317068746f47537574314a5058494463577a5a463830697a617a6c6d67696664363251472b4b6c425153487a4941755561354e5870336d5a6d59475a336e725a763063553755344d71774e642b594e78753858773737346c346d425a386c67356a344255365a57516a56326635567361784e6f325672466871734853386277324b506531305849526e6d2b34314c4c46712b507a70706b4b46746e784f45677456386e73646839386a7a69497a5a69474f7a655131677633713457344c3044644252616747536578796a5a52594a6b624f33686e7273326462576e79335271355a2f51534564416c34434d6c7a74444565536a4b68683144327a56772f61634c7a644647442f434a6a417169386f66486334725237706b4b525837507049375677425556526459584a4b54594a6f536f4858594a536539634d56344f7446794b686c736b6b726d6d7655304e6d544d715876397953795070545046642f66444e5368796f6a42753239793569626e436c63652f686f544a5a512f3358426f4853486235617445394e6c4f373135594566614852354a544537636f617952634e416554696379344e48554d66684b4531696a3257474a45374654546a4d336f4d5a5452486354473942682f2f4a434f54393131466d566e6669676f523172336e56716e47516d4333343954593262574b744f6f454c77746538722f444d47497a65744d5753456c30447173396c49596842625a397a53547747447a7972357a363533434f4a7047524636704a7468593277436e31657a7130775832767464654b53744a42626c656c6e3261494e72736f4b36616973336c63756a6753344a6c794c4a6756596a773651795365682b5a6a3946587747676c6e32796e41304c71526d4a4642446e46584b2b314765513070754455764543527a4e416c7a3661434c67566c4966715668533961496c37656d546353342b6555757956474b6f42416947737a776a6f3852772f5841484e756b4b716f486f54786d3979536642627a7072377049444b654e77484b734f45502b3676356130316b2b4f37574b3543415664793030464476345639656e71555a4e6e6f322f33763636777a6f6d626d59784859534a2f4855314439485777554c44676f66745141504143665162784d54696b6250765541527359364a47596c394f6a7a5752322b69724d5851476c2f78714b334b5a735075676b6434356f32654c713961457457545031664f677874596434357457705a694e495136344d4b7a72436662494e6c3061414d4c7a46416a397436642b3044752f4d765334555641434f58335565454e516b6b3851476c34505942504f504f35543135504b7051694c377a63787047375843584666685a6a32457569766d584c7854544e4a4573424d476c46583176417267305451586b5772456b332b6b765a646a713666785133766765554c385854353956374e57374d51646c775771377278343677346e51306374615068664d425a7752376e312f6c4a4e322f336f3552586c666a505066794549303161784533415272475a56774c69766b69304848356f624e7552394e336c77415377634e6c303154777261547a41467a6e4d774f6d516e494642492b4d6f61334e56414a69445a5665452b5873656c667461797967493957633659557355554d636b6b68524f38696b7870747255595645525149322b385971504774443738326171465031797430675543334d783330413166597a2f494a396a4f653149727767494c595874477343735058363754753230395174447a7370346945665a59642f69794f5069785974304570484267524d7157574168414851754933662b76506d706d38376d516c6e6e61625352436334614e71496a4a5975507754434b56493850696565544454622b6c327966446847327a357241507136383959453359323776394149703049384c342f68464674533871454b32764737787336777843394979746357754a6f39654a3476735a793453783568427a42346a61706f65314252656758342f6c53674e4c4c584765774b70623944336a454349557577454831666351344a5a346c4b514b61414552485152354f316f375a39744e5374344b454c5648322b426470614845496c66502f375a45316254506f573133574b6f337077544536644d47432b4674384a42393736627479775757576665542b682f776133553246526e694b654d44322f703876415969667877746d636b5a3735764e457866773855784d57312b5937324f2b546e646e78684434744d694c6243396f4544745a7a434634567a2f5351746c6958346f504b31707a617664663074472b6256486252796d43787836445a644a4459505a736379674d61394f32323237667672696243503954434579716c63634630466966413562776e5347753275374c416b6f62667268433335616a6170446730743870316f57316f396869774467556166567966766e4a384d70457a4e487838746a755642756a4b72577576557072372f634f4a3039624b6247504856564d66345569344d347646486930655a61383766552b6c396532507948722f722b583675524d66776c2f33313654504331664b70356a755578742f626f6c4d70714f46494c52436d75565a7748734731304d6965596941576d667539754b7a7462497659774a35696e4262797a5846573537614c324a31635a67626b4f32497438786d534b67515472534a2b4e7447322f2f72617763465837674d4b4b674137366f3552574a3761626458514244772f664753426d54343032454d78596a3759504e323450534a56413476316b656f3451594336683956222c2022704c36756473467650714f50765a79573469424d37773d3d225d",
+ "logIndex": "0x2",
+ "removed": false,
+ "topics": [
+ "0x95a0995b4c5d3ebf897b744ddb885dee97499f6e543f66a640081f23f85a1b39",
+ "0xcc09b2a08a988809c2389e417ff287ed608b1b1064a593c0fdf829300f4d664e"
+ ],
+ "transactionHash": "0x7e35b28d2e78031b91accd93d62131adcf699818f2d91f3426fc68af2941dc4c",
+ "transactionIndex": "0x2",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ },
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0xa6fd622086a70a937f271784a4238041698055085014230db54b885b8267598c",
+ "blockNumber": "0x1f49a5",
+ "data": "0xff064693d4d550251bd77b742dc82c42df9eb0ec78a30909c8d75ee56e6dbdee00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000002d47373682d727361204141414142334e7a61433179633245414141414441514142414141434151444d3854567a67326b6c2f35567850486a706d6b5952577a347a37565939505262667365496f7a39553270596235377168314777776147454a4758557255446258386362515259417a4d38642f4e495951386631303531495056422f3173396e4f494c624748756375344c665349576b462b59325368685a32676a6a7731743669513048344a336569495638454c57312b41504259414966727244372f50434f316d74634439322f427059304c3244625677394963644b43533141347667694e6a68482f76734d34307338584f446e66484142686d4f5461676152786f414a304f4e504b412f5737543436596c4c4b2f5832374659486c7a4e364b4d696a763153556859462f55336871355248617846427a38586e726b543646672f5235432f6d706849596c686e33456e473849384d6c466863315569777a765230364b5958564138556459634a4533327670586b664c414e416e444974456859495362424e56566e4c57456c2f496f686b7136627975353841476b5673493248566975746b4c6b6a6370454c65574d584a7430315174786438722b3634433037527232373774654e696939706d34344868476759657a353157474b4d524c68534435422b6b55734d6a564e3732455633684657754d4f44442f514c585565515062323655376530383755714d5735536e2b4e414866385838725362385251506633506e725a6a506f735961596f7873675141354e6a536b664467535046347646314d597455524568424f6146454d744f75697a595470726f6d2b79317978674f5946732b35564f77316e65456655656b4b426b4e7678555a6a2f4f36324270356a577450687734523975466e7947393270486d4a537043416a3667386f4433714c514d566e4b485951684951334e4b374c62705a466d683347614466725030597439496b71697839456d54306b507631513d3d00000000000000000000000000000000000000000000000000000000000000095b362c20312c20315d",
+ "logIndex": "0x0",
+ "removed": false,
+ "topics": [
+ "0xb0ea96c9bd0971b86af31861a476f136b65848a43bc0e9df67995a1a3ef2d972"
+ ],
+ "transactionHash": "0x3df8e74a446be9cf4410d788c6ecedb7d80095a1c9d916236ffc95555534cdcd",
+ "transactionIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ },
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0x21f8c0f1e91fb793e8b2af7f8e9d7b63e1bad0bdf83e90a002680401a43f2922",
+ "blockNumber": "0x1f49aa",
+ "data": "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001f49c30000000000000000000000000000000000000000000000000000000000000c285b2252465343724b314a42367958747448326762674e4d4f56335754366447784438654d3471364e654359466f6a425350424b456367495863746a6168366b78486d6b4869377543565656756875614f706f67544259565058644c4d31612f354845504851696959766d434779696c7053524e654a7a49736b4e71426b6a635254484e3565487a58314574554463475834535a5273484e415866656e744858377452507739574d4a323165662b6f487963397a6237584d486b4f4f762f7474434e346f4a3978647630623551745963725661747437505632577165474c6a6c417a6a76726d647675316f344e6e72686d763745536b337131325a4c372f616c63416a3478474d50657a50516f6a74566c4d41713631336662583575314f5a4e48356563386f3734446a6f654d75687a5931555a5258446d3668656f676f4e70324a41554b49466c4b356267742b4e557a43557061593541336a50376f2b59625846732b506b692f647a2f58324830693845495653616c31456169414a62416c6859777466666b4b53767a43387161534832384d3852366d472b7852476741503250564a7357773670692f6e3563764a5133326549676a303372774958526654716753576b51353257436248484374735366325652775873724755714d4270374f375831583538383073416674326151332f464775725a4e72484e382b3655374b6b6c42315a6857384e394c38445a69703763783162623438674178597444564e6d416b64434770394439673630313449596458416a7449793641466b704b6d69642b5474573235516c4342316336625245796f7a53393931552f71354971466964446a30735942516f7076533273616b4b517a64682b2b2f66504770776a662f7a72415570434f754b66474a3979772f73736b59573755775531782b4944564a7266734f4f693765535a70574d3d222c202256376d6948466b5974536c5059365266694f317358773d3d222c2022656649586b7577555362336576535a56426b41496b6d32396d4559756775676772464e7670572b656233304654736a317662777338666473513652734a6c564579474d714532745954587a434577726a76432b45494863376c7a4f6b4c46574d4975774a58396a6a4f72726f44314364723757664455757279346f64352f7659663769784b78665a32674d4a396c7277715866635861426e39443256566f6e76523665773745435a68772b6954542b517a656d6d702b2b7661334a4a3238565a454267783549466e477a48356e72304f4c343975734358696d484e4975514b6c38584f752f6e4332483666667777645274686a4f31706576537654746f3568656a7a2b7966585462386d517a6c786f462f656c5732356538494e67675a4266745347375361324e2f68396e6a4a3738304a6d5575616450524b314e623645746c6a61475233512f4c787853634641455a676c686858356667622f4e64636a6d546a486e616469524d566842697939492f376c553570755a466a53694769436d504a37726f38336b304b74397674357942456459744c6d6368314c436278692b3845496c45336a6b77627878703450476b626a5348596b305a6b69536e4c354e574b4a4d546e5538583233664b5558346a5551575647374f4f4e7472714d6264724a577a4b617a69784948337241544b5273743139484931487868456c454943626b4261473575427547596e596375394e734a44722b69622b3373787752725a2b727439516855594659674f53537a744c5a3768484a483272344b622f587a6434575762456f747854774f337a496a587458383465415a316f545a683351416e386d382f337a655771672f7142396f34506a4449494a356b57486769505558673636624b6971426e49676c67766b4e59395050643348592f6e6e76764f6a6f7674566d61714b4a43484e6d59413856644c647330364b79644b6b6e575261525a6a5131684b7039574d707a4139703462726d314d537777326350564b617a66507a656a4b73456943382f493978476156372f6a37727a776e654a3752386c6937656b30716477692b356434445376427168326e4a4e596a56383078635869555272644c674765416b714c7a783042495062625559395a5a54314879667346344639695a64754c6a5a463575766d77714e364b425854546d6477506462434f71696f616447412b676a6a4537764155654573754d792f4156652f3058394f486b4b4e7163445959474b466f6f70344c517743366d42544b6d3172544852302f336a7539706751585563314646666d45325572584c58686a2f6b364c6c2b64716f61676978344933694955444e54664677435a685048427a2b566e617346636764376a75614647396147544470486c6378496f514570754d614f3575505639537030316a4f772b464e525a317a5039433331616d637867547935354f7672644e4b6a355a2b6f44635658464e647839756b5a616676482f764843614c6d4d6839316d462b787652442b37484a514d54545656432f57684f3377792b4130342f75452f57714b2b70787270346b7a6d4762484b4c7179793852322b4a784930574c5645574573355a776e5747574b68336b587956574f334278656145724a642b3234304f5634416a62473866413367685572346f6330674c6f4e3630677132644850704e547a50426b4b6e30416771485a3674474a4c674a487478357a334b66735739564b5936707767775772683370497958696e313862567036474a363433595454557666702b7877384d365244716f7341376c474e47533845327370784953327778514b6d7749526a5039454c36422f565030316654436a6163705135534d3943452f426b49647451432b32725752437244434d4d74702f463478344a3563494b4745796f6d3261614b594950463072726778305a2f46464c79505252622b2b78616e5a34755a6858426d517a304e634b4f372b6c566135443847656e5a593041706e633074667064486b49454242785052345448566844687847542b53737350456e7a51386b37736965457242786e4a653474464f3431794c416a3675384147314f4b336756685845426e586375752b4b38622b305151522f4f52594931334c54333638474d4f75764d31683279417554464a7748585045383057346b4e65646568792f6d443933682f396f756146465656765778794e30676356364262456a79476f7644333638335263746453516430786d3835712b554d6946733449625a7a4a45416e56324d6a3957536b55766c48783452494b4e435651557230386e4453523639637a5a6436456f4957516e73532f32584979575a47714776466e52525774484f6f4a6d693952562b6e4a4a334a395770626d52566e4f5175336c62563563556d736a3462356e6e69586673566b6531723759627a7657302b734c457763414d44514d69795239413236464e615a71456b3569783264624831316d616d67357955564d4a3470726c41435141673162477a31557857687941546e3574434d52376c5334584173486c343954326b4e336a3148534e6f53354f4b6f4c55585652736f4c634530685056785131646736304555444b525536596f647873746a35504a7163374b663736634c5377473064706a71657656336f2f364b6a506950774d664977384361474f6d712b6471664f4c4c73446630436a6d375070664548386d7055667567714871453478543735316257507731392b336c59634a7831596d6c62675157334743544b7039774d6a4d68454361545152464e5963353778526d64456d4e6f4f55626d325863313942304b56646764336b6141563433436e4474767a716b634f3353496c396a48714a4339336f69334d374237356a734849686b742f2b30636e7572544151415a6c4b2f55594b304c34554d4b5a4e595030643369557449684e6356356b767041505631465347316e666e4b2f6f635955426d376a4e4253612b794c3833764c313246303149306637305a536c7135595632504f6b36786544507a614d426638676433497263356c4d4c76767132724874732b4972575a576b444f396144726458656f5845525856686872474d513632346c3439786d41306b71326c596679792f67786d706762424366416f41414a6b35687573656e634b6f4b335065634a6a6330396f7951796334777263346739553753556d58744e6933366768725274547732703762386332394d537273505779564c514c347343686a2f5a514933694b5470763931335a65724b385330513d3d222c20227256556155706c727731746643764d636d6a694570413d3d225d",
+ "logIndex": "0x0",
+ "removed": false,
+ "topics": [
+ "0x95a0995b4c5d3ebf897b744ddb885dee97499f6e543f66a640081f23f85a1b39",
+ "0xff064693d4d550251bd77b742dc82c42df9eb0ec78a30909c8d75ee56e6dbdee"
+ ],
+ "transactionHash": "0xa5de64891d8218df419932771b2030763f09e7b2f161278884970da60431a417",
+ "transactionIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ },
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0xb24fb5bd993fec7074d970b834b23c1b3a24be662c7fefa8669a87c2abc24f0d",
+ "blockNumber": "0x1f4a24",
+ "data": "0xf70d200b2eba946912ec89ba79e954bc9524f95218e398cfbe6e910e33a7713900000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000002d47373682d727361204141414142334e7a61433179633245414141414441514142414141434151444d3854567a67326b6c2f35567850486a706d6b5952577a347a37565939505262667365496f7a39553270596235377168314777776147454a4758557255446258386362515259417a4d38642f4e495951386631303531495056422f3173396e4f494c624748756375344c665349576b462b59325368685a32676a6a7731743669513048344a336569495638454c57312b41504259414966727244372f50434f316d74634439322f427059304c3244625677394963644b43533141347667694e6a68482f76734d34307338584f446e66484142686d4f5461676152786f414a304f4e504b412f5737543436596c4c4b2f5832374659486c7a4e364b4d696a763153556859462f55336871355248617846427a38586e726b543646672f5235432f6d706849596c686e33456e473849384d6c466863315569777a765230364b5958564138556459634a4533327670586b664c414e416e444974456859495362424e56566e4c57456c2f496f686b7136627975353841476b5673493248566975746b4c6b6a6370454c65574d584a7430315174786438722b3634433037527232373774654e696939706d34344868476759657a353157474b4d524c68534435422b6b55734d6a564e3732455633684657754d4f44442f514c585565515062323655376530383755714d5735536e2b4e414866385838725362385251506633506e725a6a506f735961596f7873675141354e6a536b664467535046347646314d597455524568424f6146454d744f75697a595470726f6d2b79317978674f5946732b35564f77316e65456655656b4b426b4e7678555a6a2f4f36324270356a577450687734523975466e7947393270486d4a537043416a3667386f4433714c514d566e4b485951684951334e4b374c62705a466d683347614466725030597439496b71697839456d54306b507631513d3d00000000000000000000000000000000000000000000000000000000000000095b322c20312c20315d",
+ "logIndex": "0x0",
+ "removed": false,
+ "topics": [
+ "0xb0ea96c9bd0971b86af31861a476f136b65848a43bc0e9df67995a1a3ef2d972"
+ ],
+ "transactionHash": "0x750b31b88abafe955ed0f862bd198ab794a11097be07339cf45e24369c73bc58",
+ "transactionIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ },
+ {
+ "address": "0x1c81079b0752881f3231318a1355e21de26bbeb5",
+ "blockHash": "0xa452c1df4c7d4c62619bb614b22458d04fbf6341daca7a981446a67c4feba6be",
+ "blockNumber": "0x1f4a27",
+ "data": "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001f4a410000000000000000000000000000000000000000000000000000000000000c2c5b226e2f6b766f41364276524b366c417771644c7149542b43486f6659424c73732b42586757624457736e2f7579496d7950424d666b6d39676473346d4465794546544a35787a3449674f467a506539764c384d7552714830524645524a5555703742636c305241447842692f756f3156554774544149634e5a686f355233544d4a394e694d44726c666a53522f2b7948755166554433774b34625a457155637754452b6269755231345343334c7a7564477573506c71544f346b5a796463776458484d3835575263796e3576393174765a5072644e445a4a38316858786a48596d5a785150594150544d6e417771476a645a556248326f58587866526d77374f47677a534f496d4442554867564867305578624e2f4e7976704a70766c566c6c526f464f6439587871435278632f79527967484e6b3232434b316d6b3757464d427954365842554b32375a44476d375775787931535833416d4b6a7639614a5350496341527155444b48365476316a3937364c6b324a666345706b424836344e70614a5277486c5071334d59463272513150566b4a6532776c5048656e6c744e53743737524b7575564c7761554c6156732f76584c762f6567444b654a7059596e71396f593944597267735355637a66344c493558507838786f554c427348597459463474554d5a784a313338306656506f6b6e2f42346b4d2f794a635059614f55626232587378626c6b58316d536961644f482f424e5242754a5931642f717a4d4c6a3276344e6e4f764649515378554879594d6a2f746e3676587969517a56585365705273786e55612b6d4155685632494970362b5167334c5977696f57694364684e4f796768763637384641783361476e496166634f316b6e683447346970775764565576456c6e6a553675614d307a6c55746b4e36676e4b6f384f345a4f4a2f31335076656663343d222c20227a4d396f4e64412f6779614e7a4e6d4e6e754f584d513d3d222c2022654e324662474c456c784e56685175317255744b626a6c62513936384e6d59486d674a314137335431546f376135677232376e496a716e41696255524b38503566434147357a372f752f747066386478536d3470797535524c62336e4c70532f683671537541434a64323834346966344744645369557a6e514651575132416947346a376d56766a514e785371494a6e3461434b66634e524779564355796a54374c694939584d6667685342734f476637387a5143732f3965466c55397738616f6f626c6974314e344d58466f4a54646f725432784a50655a34474168356a645344634c72596b6f754b6b61387a2f61624a765362317168574c4e2f4c754d617537564c6b70332f7372726972655a5931592b4256653158746a68666543702f4e4931763568396151505a6e5871626c6b4a55573247302b32494f564757426541387334582b4a6d5052326368455569734d6f38324d6d723050587774716d664a6c7a4e43695864556b4d5a765a345962346c426c32587830544b654a6d796873344f634b694a717034714e74373643775845504d6a72392b3275354b437a674851537833697647796a547270415576336472716768507577685a416d616b763761624763544d45752b6465485945757149742f767536625457717245316334612f3932755438486171533562585a493541544a354a596a4234716b4b2f4f4b563069465044342f7a476435436d5078743257706866394337363049422f655452696d7865463966455857532b39684734566859543546666732695753745253634e3336465833497172774d744d49426f57357a7154446e3556507232612f6b4174375164654a4d79452f6e686c6e793138617569447576336254356867757a3177513779785332526d6c4d59366b37766b596151793177356a69466d5657546331473235496b34466f5933384e636d79412f55584d41716a46483846587a73492b48534e7a352f566f2f77744c456d7671516d7330615a4f64615679706d34736574686f367548657042757a65737a2b3652356746705551334b6730767763376d384332665735463553464130534d7a6d70354a4268304236354d396857656a357251696b30495942777a7461716559706f774e4b6c4b654e3178495a5862525667783454685a474b4c78704b6a4877736a3635465a4579354e427754496a65547555734a42626e4b336656497768306650445156764d544b4450774f447062366964365873696c6d6136664576614748444354456b4e3451574c654a4f725870395a5656444343787a59456a56356f4e4564593148534b64414b734a6b44496b5a3270467344644b35676863772f6f6c657758774670756278782f4c51452b706e6150547361306e677637486570554355305767415135352b592b6f3462743076784d4f4a6b41315272414b356c794a56624343713671614647442b4b6b68547962694979483457423252664a5352574b545168316d566c517a6930327574472b6633372b6775724557496c62744e423363735a5862394b52764a446f644277565961687a6f344b6d6148334a634b665a4d5731765274704b5a2b5459747042624d2b79426531546e68643151374a57424d367745326b5962682f46666d2f2b30533276304869796968482f6643765563662f7036456a42774d695331454d39482f42777a454c35434c38666f4a33714c68754a6559536c6d55794d3376783641664c72704c6334466647575a374a537a39432f6d79614163413856786d714b77504d2b736d446f384c6c4e5a4a5266673278654a6f30755a616a7a47635378615033712b766f32546b665a34434976666545397a55684a7a797650484e4a414379764f4b41697a2b536268325552754a3349544d53494e31466f657541632f757537394d36554f7633426970697141446b595a4a71336b68467870564d316c496e4641576b6e796c58487368595a6561415830566935743745597141572f4b586562452b706b70307179345236477a6f565774654b4843522b626d5a426372394c4b734459666b36327173334542754178435431724976717476665a48755538744469666f2f45522f59465a2f4c487669413473324d4550754653385377664e4866764f787054352f364c35377a48454558355a65666b5a6443694e7662612b724e4a2f5670364974482f44614e34757942335257335066364f34504459306f314f6f5867456841524a565366504f6f706c4338665252544a506c4d61503743413052334b504d354e34585162766541474562314e373765614b436f566a4d6e6f37736b415130465051445771736664353844776d774f425953653938755144614e724f66344c6b49775037787843757064632b67386b5751636e6e756f376d38787953466a535a5461495963534f61356f52633664704b617552754b554f72426f5358535a2b793934736b59355a557949374e756e78644c627868774561396f673864346c444d78493035344874462b7a41526e4d5041505658324d633947337873452f4e4c596e36532f6355353036344450693645426f4d3074344e6b6a632f362f68322b53706e47796933325070595569595077775748613344334e576b7847446e4d6674615566394e63636e6e52527063786c47516a78354b3638724a3830694c4d6479304a4d324c3463506854577766744134515274726730526b734a652b6e6444624767383652744c76734a4d674135446a3546496a7a736c354257432b4678435148656c4a573031656b756b564a684f3059592b4f6261515a6f3158465079794748504257312b2f4e4d715156394866736e69704a4444547073545032515a4f75372f4f756161423967424338775463656e39667579636a45516e552b4a382b546f72442b49374f4f66687a546f764d466735494e4b6964705a437961665178592f5844422b5436573945787230564b49786f7869593241504d436d775a4c4e6336704d536834505a334e6678344a44304b52636f383956616c7577786b34362f62744636524e7a34774d66666c672b45434e645976494c38784a4b324247532b6d48634834726d34453937696b5569327144374a486372546379646f656f7a3933494a4757373766392b744767417055517239483165376d3146656e3752326d576c764261657563574e47346139684e54424f726242776b7a516751486f6a63636a303868533546575842514431676e365541764e42335063756a68537a6878517752497068795235792f346967717a6b684f4d79222c202255374f562f6f6354543937544e555546444a783075513d3d225d",
+ "logIndex": "0x0",
+ "removed": false,
+ "topics": [
+ "0x95a0995b4c5d3ebf897b744ddb885dee97499f6e543f66a640081f23f85a1b39",
+ "0xf70d200b2eba946912ec89ba79e954bc9524f95218e398cfbe6e910e33a77139"
+ ],
+ "transactionHash": "0x9d650d80673c666d74a135df6fd2243ff7d4022f32f3e94f72fa8c2c34737925",
+ "transactionIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ }
+ ],
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 160,
+ "rpcTime": 160,
+ "rpcCount": 1,
+ "currentBlock": 2050607,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getStorageAt.json b/dotnet/Test/Responses/eth_getStorageAt.json
new file mode 100644
index 000000000..5fad0cf7c
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getStorageAt.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9279143,
+ "execTime": 3892,
+ "rpcTime": 3890,
+ "rpcCount": 1,
+ "currentBlock": 9279505,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getTransactionByBlockHashAndIndex.json b/dotnet/Test/Responses/eth_getTransactionByBlockHashAndIndex.json
new file mode 100644
index 000000000..ef1ade5c5
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getTransactionByBlockHashAndIndex.json
@@ -0,0 +1,37 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "blockHash": "0xd03f4a0ce830ce568be08aa37bc0a72374e92da5b388e839b35f24a144a5085d",
+ "blockNumber": "0x8e32b5",
+ "chainId": "0x1",
+ "condition": null,
+ "creates": null,
+ "from": "0xe3649077ce21a48caf34041e983b92e332e80fd9",
+ "gas": "0x28b0a",
+ "gasPrice": "0xba43b7400",
+ "hash": "0x234555975ebebea0d0a1b6d3a570f8d7d50e02bbf705fd9b6764832879530d42",
+ "input": "0x",
+ "nonce": "0x9b",
+ "publicKey": "0x38d5ce4dc7e9bca12c677290487f7ea255dd9de2fabeb5f314a4f3517779b2a75861246ed7e4628a702fecd0d321ff05f963a2603b86074a79013f92330de4ef",
+ "r": "0xe4607fffc3c7e90d88201f9bbfa332ce280a559b285f06e95a7e267aa4708e07",
+ "raw": "0xf86d819b850ba43b740083028b0a94f5bec430576ff1b82e44ddb5a1c93f6f9d0884f387adefab4e1e54008025a0e4607fffc3c7e90d88201f9bbfa332ce280a559b285f06e95a7e267aa4708e07a05c8a7fbecde748b572eca35fe9a39e28ba52431e8758672c589661a86d5d3ee0",
+ "s": "0x5c8a7fbecde748b572eca35fe9a39e28ba52431e8758672c589661a86d5d3ee0",
+ "standardV": "0x0",
+ "to": "0xf5bec430576ff1b82e44ddb5a1c93f6f9d0884f3",
+ "transactionIndex": "0x1",
+ "v": "0x25",
+ "value": "0xadefab4e1e5400"
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9318885,
+ "execTime": 51,
+ "rpcTime": 50,
+ "rpcCount": 1,
+ "currentBlock": 9319117,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getTransactionByBlockNumberAndIndex.json b/dotnet/Test/Responses/eth_getTransactionByBlockNumberAndIndex.json
new file mode 100644
index 000000000..8c51b077c
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getTransactionByBlockNumberAndIndex.json
@@ -0,0 +1,37 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 2,
+ "result": {
+ "blockHash": "0xd03f4a0ce830ce568be08aa37bc0a72374e92da5b388e839b35f24a144a5085d",
+ "blockNumber": "0x8e32b5",
+ "chainId": "0x1",
+ "condition": null,
+ "creates": null,
+ "from": "0xe3649077ce21a48caf34041e983b92e332e80fd9",
+ "gas": "0x28b0a",
+ "gasPrice": "0xba43b7400",
+ "hash": "0x234555975ebebea0d0a1b6d3a570f8d7d50e02bbf705fd9b6764832879530d42",
+ "input": "0x",
+ "nonce": "0x9b",
+ "publicKey": "0x38d5ce4dc7e9bca12c677290487f7ea255dd9de2fabeb5f314a4f3517779b2a75861246ed7e4628a702fecd0d321ff05f963a2603b86074a79013f92330de4ef",
+ "r": "0xe4607fffc3c7e90d88201f9bbfa332ce280a559b285f06e95a7e267aa4708e07",
+ "raw": "0xf86d819b850ba43b740083028b0a94f5bec430576ff1b82e44ddb5a1c93f6f9d0884f387adefab4e1e54008025a0e4607fffc3c7e90d88201f9bbfa332ce280a559b285f06e95a7e267aa4708e07a05c8a7fbecde748b572eca35fe9a39e28ba52431e8758672c589661a86d5d3ee0",
+ "s": "0x5c8a7fbecde748b572eca35fe9a39e28ba52431e8758672c589661a86d5d3ee0",
+ "standardV": "0x0",
+ "to": "0xf5bec430576ff1b82e44ddb5a1c93f6f9d0884f3",
+ "transactionIndex": "0x1",
+ "v": "0x25",
+ "value": "0xadefab4e1e5400"
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9318885,
+ "execTime": 502,
+ "rpcTime": 501,
+ "rpcCount": 1,
+ "currentBlock": 9319117,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getTransactionByHash.json b/dotnet/Test/Responses/eth_getTransactionByHash.json
new file mode 100644
index 000000000..6bc09f478
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getTransactionByHash.json
@@ -0,0 +1,37 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "blockHash": "0x8220e66456e40636bff3a440832c9f179e4811d4e28269c7ab70142c3e5f9be2",
+ "blockNumber": "0x8c2e8a",
+ "chainId": null,
+ "condition": null,
+ "creates": null,
+ "from": "0x3a9e354dee60df25c0389badafec8457e36ebfd2",
+ "gas": "0xf618",
+ "gasPrice": "0x89d5f3200",
+ "hash": "0x6188bf0672c005e30ad7c2542f2f048521662e30c91539d976408adf379bdae2",
+ "input": "0xa9059cbb000000000000000000000000544d972d551061fc8e15e600f24f19021b8dfcfd000000000000000000000000000000000000000000000029097c413dfab40000",
+ "nonce": "0x8",
+ "publicKey": "0xaac8d634292b610ea2a3201dad48b332c3ee8832ea014842dfc4f5bf8b42a1c3db1410befe84db95011f3fa48ddc38c3af75fbb5782a3612512f740f56814941",
+ "r": "0xf586d0e8bb1892e56b90350daf872f3ed45baa9aaf86afd3e08505be985d089a",
+ "raw": "0xf8a90885089d5f320082f618945b8174e20996ec743f01d3b55a35dd376429c59680b844a9059cbb000000000000000000000000544d972d551061fc8e15e600f24f19021b8dfcfd000000000000000000000000000000000000000000000029097c413dfab400001ca0f586d0e8bb1892e56b90350daf872f3ed45baa9aaf86afd3e08505be985d089aa03a19b0eaa71cc931483e1f5c79b239c4c5fff91bc87092b85df36dc8786bdf2c",
+ "s": "0x3a19b0eaa71cc931483e1f5c79b239c4c5fff91bc87092b85df36dc8786bdf2c",
+ "standardV": "0x1",
+ "to": "0x5b8174e20996ec743f01d3b55a35dd376429c596",
+ "transactionIndex": "0x1d",
+ "v": "0x1c",
+ "value": "0x0"
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9278788,
+ "execTime": 42,
+ "rpcTime": 42,
+ "rpcCount": 1,
+ "currentBlock": 9278816,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getTransactionCount.json b/dotnet/Test/Responses/eth_getTransactionCount.json
new file mode 100644
index 000000000..7c14f2e8d
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getTransactionCount.json
@@ -0,0 +1,5 @@
+[{
+ "jsonrpc":"2.0",
+ "result":"0x13",
+ "id":1
+}]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getTransactionReceipt.json b/dotnet/Test/Responses/eth_getTransactionReceipt.json
new file mode 100644
index 000000000..0df77b127
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getTransactionReceipt.json
@@ -0,0 +1,47 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "blockHash": "0x8220e66456e40636bff3a440832c9f179e4811d4e28269c7ab70142c3e5f9be2",
+ "blockNumber": "0x8c2e8a",
+ "contractAddress": null,
+ "cumulativeGasUsed": "0xa11af",
+ "from": "0x3a9e354dee60df25c0389badafec8457e36ebfd2",
+ "gasUsed": "0xa4b1",
+ "logs": [
+ {
+ "address": "0x5b8174e20996ec743f01d3b55a35dd376429c596",
+ "blockHash": "0x8220e66456e40636bff3a440832c9f179e4811d4e28269c7ab70142c3e5f9be2",
+ "blockNumber": "0x8c2e8a",
+ "data": "0x000000000000000000000000000000000000000000000029097c413dfab40000",
+ "logIndex": "0x1",
+ "removed": false,
+ "topics": [
+ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
+ "0x0000000000000000000000003a9e354dee60df25c0389badafec8457e36ebfd2",
+ "0x000000000000000000000000544d972d551061fc8e15e600f24f19021b8dfcfd"
+ ],
+ "transactionHash": "0x6188bf0672c005e30ad7c2542f2f048521662e30c91539d976408adf379bdae2",
+ "transactionIndex": "0x1d",
+ "transactionLogIndex": "0x0",
+ "type": "mined"
+ }
+ ],
+ "logsBloom": "0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000010004000000000000000000000000000000000000000000000000002000000000000000000000100000000000000000000000000000000000000000000000000000001002000000080000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000",
+ "status": "0x1",
+ "to": "0x5b8174e20996ec743f01d3b55a35dd376429c596",
+ "transactionHash": "0x6188bf0672c005e30ad7c2542f2f048521662e30c91539d976408adf379bdae2",
+ "transactionIndex": "0x1d"
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9278788,
+ "execTime": 69,
+ "rpcTime": 68,
+ "rpcCount": 1,
+ "currentBlock": 9278861,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getUncleByBlockNumberAndIndex.json b/dotnet/Test/Responses/eth_getUncleByBlockNumberAndIndex.json
new file mode 100644
index 000000000..87f8ec053
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getUncleByBlockNumberAndIndex.json
@@ -0,0 +1,42 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "author": "0xea674fdde714fd979de3edf0f56aa9716b898ec8",
+ "difficulty": "0x76b922409edec",
+ "extraData": "0x505059452d65746865726d696e652d6575312d33",
+ "gasLimit": "0x9411dd",
+ "gasUsed": "0x93faa8",
+ "hash": "0x310541c7cfd2e636ed54424177474b263b0f3f66babe751db2cf2ed0adce2335",
+ "logsBloom": "0x2040834082cf1919100022504401825712a813005519488c123014920ae28d9b44c29965ecd460118930e52287424f065c2b86a00b2864a3e28ca60b20bc834c10044a00427a80851c00814a2889c8dd36070b06130d26142ad2c124106c7c7350521e289a8164034d04d2e20004980107b5163a11bca07110084112100420129c24461ec74504181a06250080692e9194484fc14a2aa4774083370040f60141968e2029012c5d848504328600f4809127180c01b085a46000c4bdc51ab08d6540bc03d2e0ba5659a69862504e4f902268117226410b40d4282208d4507d6854c01f04251400105bf56840217b0bf2c98a1b2a41820a03801216b20c291e536c",
+ "miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8",
+ "mixHash": "0xf1ce3d31274ff65f73547987893a6371adf8f939b9a3106e588d7689faf49f67",
+ "nonce": "0x50a91bf003008e2f",
+ "number": "0x8e2e6e",
+ "parentHash": "0xe1808ce3103914ba5bc0079422f2034c145698103f9ab14d602abb144755a630",
+ "receiptsRoot": "0x64a88d962f99e4226a1f3a36966e07f2c9da040cb008b68d65b8b664598b2f1c",
+ "sealFields": [
+ "0xa0f1ce3d31274ff65f73547987893a6371adf8f939b9a3106e588d7689faf49f67",
+ "0x8850a91bf003008e2f"
+ ],
+ "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ "size": "0x90e0",
+ "stateRoot": "0xf4180213c70b54ccac843b1a1aa202850a5ca9dd57f231a2519c5fcd3c8f0a1d",
+ "timestamp": "0x5e258b7b",
+ "totalDifficulty": "0x2ea783c3d341f8f178c",
+ "transactions": [],
+ "transactionsRoot": "0xf74e7e395ec3f76c09c6702ca779850e50bfcc4aae7018168e487435a7594c0d",
+ "uncles": []
+ },
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9318885,
+ "execTime": 636,
+ "rpcTime": 635,
+ "rpcCount": 1,
+ "currentBlock": 9319039,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getUncleCountByBlockHash.json b/dotnet/Test/Responses/eth_getUncleCountByBlockHash.json
new file mode 100644
index 000000000..0a1e3850a
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getUncleCountByBlockHash.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x1",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9318885,
+ "execTime": 47,
+ "rpcTime": 47,
+ "rpcCount": 1,
+ "currentBlock": 9319052,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_getUncleCountByBlockNumber.json b/dotnet/Test/Responses/eth_getUncleCountByBlockNumber.json
new file mode 100644
index 000000000..397fc5f27
--- /dev/null
+++ b/dotnet/Test/Responses/eth_getUncleCountByBlockNumber.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x2",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9280048,
+ "execTime": 58,
+ "rpcTime": 58,
+ "rpcCount": 1,
+ "currentBlock": 9280257,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_sendRawTransaction.json b/dotnet/Test/Responses/eth_sendRawTransaction.json
new file mode 100644
index 000000000..6edcb037e
--- /dev/null
+++ b/dotnet/Test/Responses/eth_sendRawTransaction.json
@@ -0,0 +1,5 @@
+[{
+ "jsonrpc":"2.0",
+ "id":1,
+ "result": "0xd5651b7c0b396c16ad9dc44ef0770aa215ca795702158395713facfbc9b55f38"
+}]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/eth_sendRawTransaction_1.json b/dotnet/Test/Responses/eth_sendRawTransaction_1.json
new file mode 100644
index 000000000..b546c6376
--- /dev/null
+++ b/dotnet/Test/Responses/eth_sendRawTransaction_1.json
@@ -0,0 +1,16 @@
+[
+ {
+ "jsonrpc": "2.0",
+ "result": "0xd55a8b0cf4896ffbbb10b125bf20d89c8006f42cc327a9859c59ac54e439b388",
+ "id": 1,
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 2004774,
+ "execTime": 318,
+ "rpcTime": 318,
+ "rpcCount": 1,
+ "currentBlock": 2038996,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/in3_nodeList.json b/dotnet/Test/Responses/in3_nodeList.json
new file mode 100644
index 000000000..16010c6af
--- /dev/null
+++ b/dotnet/Test/Responses/in3_nodeList.json
@@ -0,0 +1,201 @@
+{
+ "id": 1,
+ "result": {
+ "nodes": [
+ {
+ "url": "https://in3-v2.slock.it/goerli/nd-1",
+ "address": "0x45d45e6ff99e6c34a235d263965910298985fcfe",
+ "index": 0,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1dd",
+ "timeout": 3456000,
+ "registerTime": 1576227711,
+ "weight": 2000
+ },
+ {
+ "url": "https://in3-v2.slock.it/goerli/nd-2",
+ "address": "0x1fe2e9bf29aa1938859af64c413361227d04059a",
+ "index": 1,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1dd",
+ "timeout": 3456000,
+ "registerTime": 1576227741,
+ "weight": 2000
+ },
+ {
+ "url": "https://in3-v2.slock.it/goerli/nd-3",
+ "address": "0x945f75c0408c0026a3cd204d36f5e47745182fd4",
+ "index": 2,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1dd",
+ "timeout": 3456000,
+ "registerTime": 1576227801,
+ "weight": 2000
+ },
+ {
+ "url": "https://in3-v2.slock.it/goerli/nd-4",
+ "address": "0xc513a534de5a9d3f413152c41b09bd8116237fc8",
+ "index": 3,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1dd",
+ "timeout": 3456000,
+ "registerTime": 1576227831,
+ "weight": 2000
+ },
+ {
+ "url": "https://in3-v2.slock.it/goerli/nd-5",
+ "address": "0xbcdf4e3e90cc7288b578329efd7bcc90655148d2",
+ "index": 4,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1dd",
+ "timeout": 3456000,
+ "registerTime": 1576227876,
+ "weight": 2000
+ },
+ {
+ "url": "https://tincubeth.komputing.org/",
+ "address": "0xf944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a",
+ "index": 5,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x1d7e0000000a",
+ "timeout": 3456000,
+ "registerTime": 1578947320,
+ "weight": 1
+ },
+ {
+ "url": "https://h5l45fkzz7oc3gmb.onion/",
+ "address": "0x56d986deb3b5d14cb230d0f39247cc32416020b6",
+ "index": 6,
+ "deposit": "0x2386f26fc10000",
+ "props": "0x21660000000a",
+ "timeout": 3456000,
+ "registerTime": 1578954071,
+ "weight": 1
+ }
+ ],
+ "contract": "0x5f51e413581dd76759e9eed51e63d14c8d1379c8",
+ "registryId": "0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea",
+ "lastBlockNumber": 2320627,
+ "totalServers": 7
+ },
+ "jsonrpc": "2.0",
+ "in3": {
+ "execTime": 46,
+ "lastValidatorChange": 0,
+ "proof": {
+ "type": "accountProof",
+ "block": "0xf9025ba055f6b4aa91745fbb52cf97670818aa02b322f02d1493ae12b00248db7714da33a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a053dfa5bed7fcd8db8e53f62d89a9d0150f100d94bc4012a5fc0021bd40e54af2a0816933a656d094e3839b1c8451ec1c7b7fa3417008d866bdc1d3c40c699b412aa0a016a3e03d190d68ed522721348ab73e351de580cfe6cc0599c1ef3ce4e970eeb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832368f3837a120082520c845e677e57b86144505020417574686f726974790000000000000000000000000000000000000023f9a4d677658cc5769bc4155255f804fca774641e5e7ee3ba3b37c0d261ea5036bb37cf6ab5d88e1210b8544022fca17fcd99d0b90abcf30d0fea71d550793800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000",
+ "accounts": {
+ "0x5f51e413581dd76759e9eed51e63d14c8d1379c8": {
+ "accountProof": [
+ "0xf90211a07f2fcbf477f78c116a1ae210b6c809bd9de8c746d897f01df8325257eac8fa2da0da3247da1c9b573bb0f949dccd06d741d23f573a971a2fd22bb813b0db125475a0af84436894eebbe2c25c8cadd1f2aaad3e5d780be5d5885df9666f41a195c486a0f912828f6a75bbfd5c34b5f38ce67d520ed8c7c6a81996a94db0d7d673aaff34a034485e46b6a9e4287c0457dab61a8d043aa34b6bc2920994c017f69103fe70c8a006d4af0c6846b639e7f42d98213c077ac71a4ebb5239ce040208f752bd20f91ba0085bd12c921e3911120d55660e90eb0de19b626295cd44fc52e82421f6531a23a040670226521f787e8f91e602c2bda74d20fafbf8a903ebcb28baf7b853db463ea00ef26743f9cdd5cbc3c094bbd9e6aa39a3c567de88c6ca18fa8613e8f978fe32a034afa40daedd0c3260562ed477b6fd6fb8244fc7668b82ffe916dd5609c12bdca0c3f0aed8bff8e99e2d3c00cb41995af6228a65700000815492fd5ee2bd0b7c3aa0aee3e7e0867f2d4d5b32b85e41e01e1aed5d28b0f00099f2aeeab93c0607ce7ea04b86770d609b3d66c58bbe7b5c94bb958e39d34f3155029d1be1b8b23c72d8cfa096c5a37a41f65ca713add0c42ba5998402b687d3067df27de48d0442f168c0dba0d41db9d14fcac964fdfcc8792cc34948b0dd2beb72e9a41fc7cf128cdda8d91ca0d52b29b8d83fcfedd15eb55083f7d7ff7c039d4368c0c68f8564b057dc1b1de380",
+ "0xf90211a048ad2947963e563552346d01b7ff56bb854cdc67b31de8cb5f32f7b227f82d22a09e5c0a0facca3da267ac8860a86aac8dfbdbada34067928b614734b83166c6e7a05a10a9e7139931794c639f4dd13fb887423c0e032cf3728860e975ba81a974faa06552aa39f90e07d17916e4ce8e2c1e6c5f6f4b3381e6d7fc8dbc02c0d3a3dffaa00d93f1c76b4ba40c195b3bb96fc41141ad659d456b61c1440656293ad1e69a16a0fc51d5c8f47b6139c5a3ab34e664e600818c1e5d2a1cf76f3693c03cf1eb4269a0066601b2c34591323031a24394f76ccd16799efae36f4cfa1fea64586ac32df4a0065ab8064dea83dae7e1d2f2f588fe3e7667fd56746f07bd4a64cf9a3c810e78a08ff2d32d5a7fdf1c00ef53fd8d5f835ac46a992a572aef1f7a14fda3aae3a91ca04e6dece42772229aee1d6d4f732c38aff55edb23a47fe768b0cedfbfb4506c18a0b9e22f83f9aa10f9a98f2c0e0b88408222850fcf208e58bb15c7c1c6880a2524a09c3d0d005c2f696590e29c67678082c3c8b6df86aa352a5bf7321eb64413ef9ea0d461a60f8e86759996c08d2b2efc4a80e1b35122aebecb7ad266add1a72a9d42a0424c1317a88c81857236901162338928bd7784f561af667cd40693821b8d004da0fe86912529153eda23a6dc5b36ed7f76b5e0f56658417cfc0ff065fd85b271b4a06a04a3436920f8f01cfe9e2252babcfc72ecf0d36e3dc5c4f78d7f2fc8f551d680",
+ "0xf90211a07141c17f9fa7951761d2bb4fd14657ee63c26fcac0f453edcc40b53077b8cb49a011a1829719b64b2963be244e5cc70370e918f11bc0f76b3afeaad72b334bb3b0a0b8a19bab2a7fbce893d4f7fa6aebff851f91ce283cce75a956f648cfdf1cca73a001ccf1d06d5af32f277ea2f918b726604238161cf9ab496401c2d4b27cad5881a0a5ab6e572c7862950a6b4e0ad8b281954126d931eb0e4d9ce9d37ceade30917ba0db170d582739015526b62443782a481d31ef5f16bb3847044ec9245e30da9f2ba0cc05ae7a81635ec756a23040202783cce5f0ff95fc7568abeca48d99451ca58ea0e67d2d5b047d3e715ddf0dc9b7337b8d0897d4441f5f04b12246a3a0c722da3fa0d2559dcce9c8542dc07069cb8b86066b76ef6053dba01309ebf2e80aadf08d3fa0a411c30ed2e578256d2e446418216b8f590ab5e5e55e220c0d468dce23e1f761a09bcb2be34112ca0596ce9ef706c059de0415fbb8598979c5c691f8ce4509fb8ca0624edfa58969d47f3da6e6688f61dfef249a1f4ec4e5b0ba3be8c94283069edba0e60f84dfa36d07f8103be8a33bdeb46bdd619155a3abc69f6c5a9dbabd064fdaa0c6d8e810d9206e0abe24b656af58eb289d67b50dc7f6fdb8e287de71069a872aa0fb123fece0ab7b47f219fd3b8d4a3a68e928f58ae806a9a68fdd67cd2f449e87a0d65313ba3300ad622207f36a1241ac74e7b18d30b814c7074cd1c932caaeacfa80",
+ "0xf901b1a02691bcd5e32c39f4f36d5b6b03f091948eb9ca3df225ddad93eb31b8497e4c1aa08e5e2cd65a2ec84ffbc2ae1c2066139423cfe71c351a8dd42b471faeb4c05dd6a0bc2809c3a3720f2b0fae7dea4f7efedb4327a48c151b89b090ab99dee7bdcf4aa01f28521aec2d7a50a466f88281e6e827d5509bc5a77be74f3f704fd91079442da05ed7f0cf73f299255bfc2bdf20b31a709518fb71bdcaa9fb8fd488ad07af28ae80a03ecd2de48b44e54b5b892520291fd2601ddff191ba446997f3587d51e8f68ddfa097a4d6d7f15b05d96ed7511e39aae51032fc3648c15eb4d789ce8916f79a78a180a0bb081130c535bc8a46528bae3596200eb99d0b99bde40ad12b624e2466c7757ba006b3c644afc9051baca2f44b34ba9f257ffef290b157655cc5acb614127496e4a04c35b4967661e70f5068aa326f3599c7393498e1b082b8b26062f98ffbb2e8f4a023d8b0cdfc5807cf338a56b1260118129ce2d1080dca624d02c1e7a44ef7255fa068665baa882f2e62da7897273881f510f3768c3d9878efdf097085ef3f0b5ac480a0d4524fcdca73a594f45be8e41613995cdd8bd38512c6932f04f6d6787ca4856380",
+ "0xf87180a05da0431ddcf9c0df5220e90991d6fafadcbb70ec9e51c042a743f4d1980df7c4a05e856a872504286cb6dbb11c85fab4ca263a72cbee0a785053fbbb4f2d6078738080808080a09922b3a2aac38c7bd2332ec05abd047f2fb7858f2d2ae4f6c49bce18b73eae948080808080808080",
+ "0xf8679e3860ace08b3156e1e8b3657a41748919bc942fd9e0f3de90d72f6e5bdfc3b846f8440180a0ee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0ba029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"
+ ],
+ "address": "0x5f51e413581dd76759e9eed51e63d14c8d1379c8",
+ "balance": "0x0",
+ "codeHash": "0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1",
+ "nonce": "0x1",
+ "storageHash": "0xee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0b",
+ "storageProof": [
+ {
+ "key": "0x0",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080",
+ "0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56307"
+ ],
+ "value": "0x7"
+ },
+ {
+ "key": "0x1",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080",
+ "0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a067c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"
+ ],
+ "value": "0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080",
+ "0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a02b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"
+ ],
+ "value": "0x2b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880",
+ "0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a00c2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"
+ ],
+ "value": "0xc2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf8b1a0f3ab6aa3f0575916e985798d7ee01e8c75436765f043cdfba2ad10f36b47f6d48080a069a129011ab4666f131c1bdac7d923dcbb6f1047057a62d6ecede5d17057658280a064bde28657cfaa21b487ad660da11e94a06a1b7f46502263094cde0407dfd24380808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd080a015cb29fd7064f1cbac8773177854799e563e10ba66e44c5adf25b31fa39a7d3980808080",
+ "0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a098d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"
+ ],
+ "value": "0x98d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080",
+ "0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a079c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"
+ ],
+ "value": "0x79c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080",
+ "0xf85180808080a0fe0a1c808c8e90225d5dcfad8bde23daee522b2905b605bc6eb5c39596018464808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080",
+ "0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0a7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"
+ ],
+ "value": "0xa7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080",
+ "0xf843a0202f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cea1a0ac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"
+ ],
+ "value": "0xac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"
+ },
+ {
+ "key": "0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585",
+ "proof": [
+ "0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80",
+ "0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880",
+ "0xf843a0207c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422ca1a01fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"
+ ],
+ "value": "0x1fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"
+ }
+ ]
+ }
+ },
+ "signatures": [
+ {
+ "blockHash": "0x0f4988c4c7fa0fb090b6b2298098372ccc0af3b9abe3cd71e743d0a279784920",
+ "block": 2320627,
+ "r": "0xa5ba4d5442f42e8010bfaeae63a999af6b599b81c8809b3e43d638b67e2c8d4c",
+ "s": "0x499d871855bf0983709194422400dc9208c6bdafd48d2abc3a99b77819b33576",
+ "v": 28,
+ "msgHash": "0xa97b35fc1a12376ed57c1ca01bde6ca19901f4864e29fa720a763cd8f89d0f16"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Responses/in3_sign.json b/dotnet/Test/Responses/in3_sign.json
new file mode 100644
index 000000000..7201f919e
--- /dev/null
+++ b/dotnet/Test/Responses/in3_sign.json
@@ -0,0 +1,25 @@
+[
+ {
+ "id": 1,
+ "jsonrpc": "2.0",
+ "result": [
+ {
+ "blockHash": "0x2a8bf38abe3fec478a2029e74ac95ecdbef95ff2fb832786ba4c5231c8cea480",
+ "block": 9551793,
+ "r": "0x16cf7b94a7276532ceff4bf6fd50fd01f2c2962a5f0887c70c75943ce9e08b77",
+ "s": "0x01f51c90e7f3493acf3c5b4efbed63534711f6209b2c47c34074f4882b92feaa",
+ "v": 27,
+ "msgHash": "0x0284928ef6fd270bacbfdba3087d0c50ad2db74af54c8bda8209b8ac9e41cfe1"
+ }
+ ],
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 9422326,
+ "execTime": 60,
+ "rpcTime": 58,
+ "rpcCount": 1,
+ "currentBlock": 9552071,
+ "version": "2.1.0"
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/ipfs_get.json b/dotnet/Test/Responses/ipfs_get.json
new file mode 100644
index 000000000..d84d4211f
--- /dev/null
+++ b/dotnet/Test/Responses/ipfs_get.json
@@ -0,0 +1,15 @@
+[
+ {
+ "id": 1,
+ "result": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ=",
+ "jsonrpc": "2.0",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 8525528,
+ "execTime": 14,
+ "rpcTime": 0,
+ "rpcCount": 0,
+ "currentBlock": 17091918
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/Responses/ipfs_put.json b/dotnet/Test/Responses/ipfs_put.json
new file mode 100644
index 000000000..62492daa7
--- /dev/null
+++ b/dotnet/Test/Responses/ipfs_put.json
@@ -0,0 +1,15 @@
+[
+ {
+ "id": 1,
+ "result": "QmbGySCLuGxu2GxVLYWeqJW9XeyjGFvpoZAhGhXDGEUQu8",
+ "jsonrpc": "2.0",
+ "in3": {
+ "lastValidatorChange": 0,
+ "lastNodeList": 8525528,
+ "execTime": 23,
+ "rpcTime": 0,
+ "rpcCount": 0,
+ "currentBlock": 17091918
+ }
+ }
+]
\ No newline at end of file
diff --git a/dotnet/Test/StubTransport.cs b/dotnet/Test/StubTransport.cs
new file mode 100644
index 000000000..049f81777
--- /dev/null
+++ b/dotnet/Test/StubTransport.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using In3.Transport;
+using Newtonsoft.Json.Linq;
+
+namespace Test
+{
+ public class StubTransport : Transport
+ {
+ private Dictionary Responses { get; }
+ private const string ResponsesDir = "Responses";
+
+ public StubTransport()
+ {
+ Responses = new Dictionary();
+ }
+
+ public string Handle(string url, string payload)
+ {
+ return Responses[GetMethod(payload)];
+ }
+
+ public void AddMockedresponse(string methodName, string filename)
+ {
+ string content = ReadFile(filename);
+ Responses.Add(methodName, content);
+ }
+
+ private string GetMethod(string payload)
+ {
+ var payloadObj = JArray.Parse(payload);
+ return payloadObj.First["method"].ToString();
+ }
+
+ private string ReadFile(string filename)
+ {
+ string fullPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ResponsesDir, filename);
+ return File.ReadAllText(fullPath);
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/Test/Test.csproj b/dotnet/Test/Test.csproj
new file mode 100644
index 000000000..7c267f06e
--- /dev/null
+++ b/dotnet/Test/Test.csproj
@@ -0,0 +1,170 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+
diff --git a/dotnet/Test/Utils/TypesMatcherTest.cs b/dotnet/Test/Utils/TypesMatcherTest.cs
new file mode 100644
index 000000000..2eedbebde
--- /dev/null
+++ b/dotnet/Test/Utils/TypesMatcherTest.cs
@@ -0,0 +1,50 @@
+using System.Numerics;
+using System.Text.Json;
+using In3.Eth1;
+using In3.Utils;
+using NUnit.Framework;
+
+namespace Test.Utils
+{
+ public class TypesMatcherTest
+ {
+ [Test]
+ public void BigIntToPrefixedHex()
+ {
+ BigInteger n1 = -3482395934534543;
+ BigInteger n2 = 0;
+ BigInteger n3 = 15;
+ BigInteger n4 = 17;
+
+ Assert.That(TypesMatcher.BigIntToPrefixedHex(n1), Is.EqualTo("-0xC5F387CA52B8F"));
+ Assert.That(TypesMatcher.BigIntToPrefixedHex(n2), Is.EqualTo("0x0"));
+ Assert.That(TypesMatcher.BigIntToPrefixedHex(n3), Is.EqualTo("0xF"));
+ Assert.That(TypesMatcher.BigIntToPrefixedHex(n4), Is.EqualTo("0x11"));
+ }
+
+ [Test]
+ public void HexStringToBigint()
+ {
+ string n1 = "-0x0C5F387CA52B8F";
+ string n2 = "0x0";
+ string n3 = "0x0F";
+ string n4 = "0x11";
+ string n5 = "0x961e2e";
+ string n6 = "0x24e160300";
+
+ BigInteger res1 = -3482395934534543;
+ BigInteger res2 = 0;
+ BigInteger res3 = 15;
+ BigInteger res4 = 17;
+ BigInteger res5 = 9838126;
+ BigInteger res6 = 9900000000;
+
+ Assert.That(TypesMatcher.HexStringToBigint(n1), Is.EqualTo(res1));
+ Assert.That(TypesMatcher.HexStringToBigint(n2), Is.EqualTo(res2));
+ Assert.That(TypesMatcher.HexStringToBigint(n3), Is.EqualTo(res3));
+ Assert.That(TypesMatcher.HexStringToBigint(n4), Is.EqualTo(res4));
+ Assert.That(TypesMatcher.HexStringToBigint(n5), Is.EqualTo(res5));
+ Assert.That(TypesMatcher.HexStringToBigint(n6), Is.EqualTo(res6));
+ }
+ }
+}
\ No newline at end of file
diff --git a/dotnet/ci.yml b/dotnet/ci.yml
index cf328105a..f160a5406 100644
--- a/dotnet/ci.yml
+++ b/dotnet/ci.yml
@@ -1,6 +1,15 @@
+.only_dotnet:
+ rules:
+ - changes:
+ - dotnet/**/*
+ - 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"'
+
dotnet:
image: docker.slock.it/build-images/dotnet-core-sdk:3.1
stage: bindings
+ extends: .only_dotnet
needs:
- mac_os
- win_jni
@@ -9,18 +18,51 @@ dotnet:
tags:
- short-jobs
script:
- - mkdir dotnet/Debug
- - cp mac_build/lib/libin3.dylib dotnet/Debug/libin3.x64.dylib
- - cp win_jni/lib/libin3.so dotnet/Debug/in3.x64.dll
- - cp x64_build/lib/libin3.so dotnet/Debug/libin3.x64.so
- - cp arm_jni_build/lib/libin3.so dotnet/Debug/libin3.arm7.so
- - cp -r dotnet/Debug dotnet/Release
+ - mkdir -p dotnet/In3/runtimes/linux-x64/native
+ - mkdir -p dotnet/In3/runtimes/linux-arm64/native
+ - mkdir -p dotnet/In3/runtimes/osx-x64/native
+ - mkdir -p dotnet/In3/runtimes/win-x64/native
+ - cp mac_build/lib/libin3.dylib dotnet/In3/runtimes/osx-x64/native/libin3.dylib
+ - cp x64_build/lib/libin3.so dotnet/In3/runtimes/linux-x64/native/libin3.so
+ - cp win_jni/lib/libin3_jni.so dotnet/In3/runtimes/win-x64/native/libin3.dll
+ - cp arm_jni_build/lib/libin3.so dotnet/In3/runtimes/linux-arm64/native/libin3.so
- cd dotnet
- - dotnet build -c Debug
+ - mkdir Release
- dotnet build -c Release
- - cp In3/bin/Debug/netcoreapp3.1/* Debug/
- - cp In3/bin/Release/netcoreapp3.1/* Release/
+ - cp -r In3/bin/Release/* Release/
artifacts:
paths:
- - dotnet/Debug
- dotnet/Release
+ - dotnet/In3/runtimes/
+
+.dotnet_test:
+ stage: dotnet
+ needs:
+ - dotnet
+ script:
+ - dotnet test --logger "junit;LogFilePath=test_results.xml" ./dotnet/
+ artifacts:
+ reports:
+ junit: dotnet/Test/test_results.xml
+
+dotnet_win:
+ extends: .dotnet_test
+ tags:
+ - windows
+
+dotnet_linux:
+ extends: .dotnet_test
+ image: docker.slock.it/build-images/dotnet-core-sdk:3.1
+ tags:
+ - short-jobs
+
+dotnet_macos:
+ extends: .dotnet_test
+ tags:
+ - mac-mini-runner
+
+dotnet_arm:
+ extends: .dotnet_test
+ image: mcr.microsoft.com/dotnet/core/sdk:3.1
+ tags:
+ - arm
diff --git a/dotnet/dotnet.sln b/dotnet/dotnet.sln
index 4ca2e0d38..5e5848e78 100644
--- a/dotnet/dotnet.sln
+++ b/dotnet/dotnet.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "In3", "In3\In3.csproj", "{2
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "ConsoleTest\ConsoleTest.csproj", "{BC33EED8-4337-4162-A615-E64CC07AE628}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{39CFD4D5-A0E0-43BC-9A87-032474CA8A65}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -44,5 +46,17 @@ Global
{BC33EED8-4337-4162-A615-E64CC07AE628}.Release|x64.Build.0 = Release|Any CPU
{BC33EED8-4337-4162-A615-E64CC07AE628}.Release|x86.ActiveCfg = Release|Any CPU
{BC33EED8-4337-4162-A615-E64CC07AE628}.Release|x86.Build.0 = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|x64.Build.0 = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Debug|x86.Build.0 = Debug|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|Any CPU.Build.0 = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|x64.ActiveCfg = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|x64.Build.0 = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|x86.ActiveCfg = Release|Any CPU
+ {39CFD4D5-A0E0-43BC-9A87-032474CA8A65}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
index e295b4bc1..b30d3c212 100644
--- a/java/CMakeLists.txt
+++ b/java/CMakeLists.txt
@@ -14,21 +14,21 @@
# 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
+# 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
+#
+# 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
+# [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
+# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see .
###############################################################################
@@ -37,3 +37,5 @@
add_subdirectory(src)
add_subdirectory(docs)
+
+
diff --git a/java/ci.yml b/java/ci.yml
index 8f045d42f..82d3d227c 100644
--- a/java/ci.yml
+++ b/java/ci.yml
@@ -1,3 +1,17 @@
+.only_java:
+ rules:
+ - changes:
+ - java/**/*
+ - 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"'
+
+# This template should be used for jobs to run during deployment only
+.only_deploy:
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/'
+ when: manual
+
java:
image: docker.slock.it/build-images/cmake:gcc8
stage: bindings
@@ -29,6 +43,7 @@ test_android:
needs: []
tags:
- short-jobs
+ extends: .only_java
script:
- git clone https://github.com/slockit/in3-example-android.git
- cd in3-example-android/app
@@ -43,6 +58,7 @@ test_android:
java_linux:
image: docker.slock.it/build-images/cmake:gcc8
stage: java
+ extends: .only_java
coverage: '/java:\s+(\d+.\d+\%)/'
needs:
- java
@@ -60,6 +76,7 @@ java_linux:
java_arm:
image: armv7/armhf-java8
+ extends: .only_java
needs:
- java
stage: java
@@ -76,6 +93,7 @@ java_arm:
java_macos:
stage: java
allow_failure: true
+ extends: .only_java
needs:
- java
script:
@@ -88,6 +106,7 @@ java_macos:
java_win:
stage: java
allow_failure: true
+ extends: .only_java
needs:
- java
script:
@@ -99,3 +118,16 @@ java_win:
# artifacts:
# reports:
# junit: java/build/test-results/test/TEST-*.xml
+
+release_maven:
+ stage: deploy
+ image: docker.slock.it/build-images/maven-deployment-image:latest
+ tags:
+ - short-jobs
+ extends: .only_deploy
+ needs:
+ - java
+ script:
+ - touch settings.xml
+ - echo $MAVEN_SETTINGS > settings.xml
+ - mvn -s settings.xml deploy:deploy-file -DgroupId=it.slock -DartifactId=in3 -Dversion=$CI_COMMIT_TAG -Dpackaging=jar -Dfile=java_build/lib/in3.jar -DrepositoryId=github -Durl=https://maven.pkg.github.com/slockit/in3-c
diff --git a/java/gradle/wrapper/gradle-wrapper.properties b/java/gradle/wrapper/gradle-wrapper.properties
index 94920145f..2a6fef12c 100644
--- a/java/gradle/wrapper/gradle-wrapper.properties
+++ b/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
+distributionUrl=https://services.gradle.org/distributions/gradle-6.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/java/src/in3/ipfs/API.java b/java/src/in3/ipfs/API.java
index 953df2372..6b74e3eef 100644
--- a/java/src/in3/ipfs/API.java
+++ b/java/src/in3/ipfs/API.java
@@ -5,36 +5,38 @@
import java.nio.charset.Charset;
/**
- * API for ipfs custom methods. To be used along with "Chain.IPFS" on in3 instance.
- */
+ * API for ipfs custom methods. To be used along with "Chain.IPFS" on in3
+ * instance.
+ */
public class API {
private IN3 in3;
private static final String PUT = "ipfs_put";
private static final String GET = "ipfs_get";
- private enum Enconding {
+ private enum Encoding {
base64,
hex,
utf8;
}
/**
- * creates a ipfs.API using the given incubed instance.
- */
+ * creates a ipfs.API using the given incubed instance.
+ */
public API(IN3 in3) {
this.in3 = in3;
}
/**
- * Returns the content associated with specified multihash on success OR NULL on error.
+ * Returns the content associated with specified multihash on success OR NULL on
+ * error.
*/
public byte[] get(String multihash) {
- if (multihash == null) throw new IllegalArgumentException();
+ if (multihash == null)
+ throw new IllegalArgumentException();
- String content = JSON.asString(in3.sendRPCasObject(GET, new Object[] {
- multihash,
- JSON.asString(Enconding.base64)}));
+ String content = JSON
+ .asString(in3.sendRPCasObject(GET, new Object[] {multihash, JSON.asString(Encoding.base64)}));
return content != null ? base64Decode(content) : null;
}
@@ -50,15 +52,16 @@ public String put(String content) {
* Returns the IPFS multihash of stored content on success OR NULL on error.
*/
public String put(byte[] content) {
- if (content == null) throw new IllegalArgumentException();
+ if (content == null)
+ throw new IllegalArgumentException();
String encodedContent = base64Encode(content);
- Object rawResult = in3.sendRPCasObject(PUT, new Object[] {
- encodedContent});
+ Object rawResult = in3.sendRPCasObject(PUT, new Object[] {encodedContent});
return JSON.asString(rawResult);
}
- private native byte[] base64Decode(String str);
+ private native byte[] base64Decode(String str);
+
private native String base64Encode(byte[] str);
}
diff --git a/java/src/in3/utils/Signature.java b/java/src/in3/utils/Signature.java
index dc4d3e67c..f62c4bbeb 100644
--- a/java/src/in3/utils/Signature.java
+++ b/java/src/in3/utils/Signature.java
@@ -30,6 +30,7 @@ protected static Signature asSignature(Object o) {
public String getMessage() {
return data.getString(MESSAGE);
}
+
/*
* returns the hash of the message
*/
diff --git a/python/MANIFEST.in b/python/MANIFEST.in
index 721484bf7..532185678 100644
--- a/python/MANIFEST.in
+++ b/python/MANIFEST.in
@@ -1,2 +1,2 @@
-include readme.md
-include in3/bind/slibs/*
+include README.md LICENSE LICENSE.AGPL
+recursive-include in3/libin3/shared *
\ No newline at end of file
diff --git a/python/README.md b/python/README.md
index ad51296ec..43ffeb49c 100644
--- a/python/README.md
+++ b/python/README.md
@@ -12,39 +12,46 @@ This library is based on the [C version of Incubed](http://github.com/slockit/in
pip install in3
```
-### In3 Client Standalone
+### In3 Client API
```python
import in3
in3_client = in3.Client()
+# Sends a request to the Incubed Network, that in turn will collect proofs from the Ethereum client,
+# attest and sign the response, then send back to the client, that will verify signatures and proofs.
block_number = in3_client.eth.block_number()
print(block_number) # Mainnet's block number
-in3_client.eth # ethereum module
-in3_client.in3 # in3 module
+in3_client # incubed network api
+in3_client.eth # ethereum api
+in3_client.account # ethereum account api
+in3_client.contract # ethereum smart-contract api
```
### Tests
```bash
-python tests/test_suite.py
+pytest --pylama
```
-### Contributing
-1. Read the index and respect the architecture. For additional packages and files please update the index.
-2. (Optional) Get the latest `libin3.dylib` from the Gitlab Pipeline on the `in-core` project and replace it in `in3/bind` folder.
-3. Write the changes in a new branch, then make a pull request for the `develop` branch when all tests are passing. Be sure to add new tests to the CI.
-
### Index
Explanation of this source code architecture and how it is organized. For more on design-patterns see [here](http://geekswithblogs.net/joycsharp/archive/2012/02/19/design-patterns-for-model.aspx) or on [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
- **in3.__init__.py**: Library entry point, imports organization. Standard for any pipy package.
-- **in3.eth**: Package for Ethereum objects and tools.
-- **in3.eth.account**: Api for managing simple wallets and smart-contracts alike.
-- **in3.eth.api**: Ethereum tools and Domain Objects.
-- **in3.eth.model**: Value Objects for Ethereum.
-- **in3.libin3**: Package for everything related to binding libin3 to python. Libin3 is written in C and can be found [here](https://github.com/slockit/in3-c).
+- **in3.client**: Incubed Client and API.
+- **in3.model**: MVC Model classes for the Incubed client module domain.
+- **in3.transport**: HTTP Transport function and error handling.
+- **in3.wallet**: WiP - Wallet API.
+- **in3.exception**: Custom exceptions.
+- **in3.eth**: Ethereum module.
+- **in3.eth.api**: Ethereum API.
+- **in3.eth.account**: Ethereum accounts.
+- **in3.eth.contract**: Ethereum smart-contracts API.
+- **in3.eth.model**: MVC Model classes for the Ethereum client module domain. Manages serializaation.
+- **in3.eth.factory**: Ethereum Object Factory. Manages deserialization.
+- **in3.libin3**: Module for the libin3 runtime. Libin3 is written in C and can be found [here](https://github.com/slockit/in3-c).
- **in3.libin3.shared**: Native shared libraries for multiple operating systems and platforms.
- **in3.libin3.enum**: Enumerations mapping C definitions to python.
- **in3.libin3.lib_loader**: Bindings using Ctypes.
- **in3.libin3.runtime**: Runtime object, bridging the remote procedure calls to the libin3 instances.
+
diff --git a/python/__tests__/src/ethereum/ethereum.py b/python/__tests__/src/ethereum/ethereum.py
deleted file mode 100644
index 04fa84624..000000000
--- a/python/__tests__/src/ethereum/ethereum.py
+++ /dev/null
@@ -1,207 +0,0 @@
-from unittest import TestCase
-from in3py.client.in3_client import In3Client, IN3Config
-from in3py.model.in3_model import Address,IN3Number, Hash, Transaction, Filter
-from in3py.enums.in3 import EnumsBlockStatus
-
-import in3.client
-import in3.eth.account
-
-
-class EthereumTest(TestCase):
-
- def setUp(self):
- conf = IN3Config()
- conf.chainId="0x2a"
- self.eth = In3Client(in3_config=conf).eth
-
-
- def test_web3_sha3(self):
- result = in3.eth.account.keccak256("0x68656c6c6f20776f726c64")
- self.assertEqual(result, "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad")
-
- def test_eth_gasPrice(self):
- result = self.eth.gas_price()
- self.assertEqual(result.to_int(), 2000000000)
-
- def test_block_number(self):
- result = self.eth.block_number()
- self.assertGreater(result.to_int(),0)
-
- def test_get_balance(self):
- address = Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- result = self.eth.get_balance(address=address)
- print(result.to_int())
-
- def test_get_storage_at(self):
- rpc = self.eth.get_storage_at(address = Address("0xaF91fF3c7E46D40684703F514783FA8880FF8C57", skip_validation=True), position=IN3Number(0), at_block=EnumsBlockStatus.LATEST)
- print(rpc)
-
- def test_get_transaction_count(self):
- address = Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- rpc = self.eth.get_transaction_count(address=address, at_block=EnumsBlockStatus.LATEST)
- print(rpc.to_int())
-
- #TODO: ERROR
- def test_get_block_transaction_count_by_hash(self):
- hash=Hash("0x3afff6aafecec5d5d3d2abb580e9750f35ddd3bf12cd912daf8de443b2aaaeb2")
- rpc = self.eth.get_block_transaction_count_by_hash(block_hash=hash)
- print(rpc)
-
- #TODO: ERROR
- def test_get_block_transaction_count_by_number(self):
- number = IN3Number("0xd12321")
- rpc = self.eth.get_block_transaction_count_by_number(number=number)
- print(rpc)
-
- #TODO:FIND
- def test_get_uncle_count_by_block_hash(self):
- hash=Hash("0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238")
- rpc = self.eth.get_uncle_count_by_block_hash(block_hash=hash)
- print(rpc)
-
- #TODO:FIND
- def test_get_uncle_count_by_block_number(self):
- number = IN3Number(14891999)
- rpc = self.eth.get_uncle_count_by_block_number(number=number)
- print(rpc)
-
- def test_get_code(self):
- address = Address("0xe323f6a06AbFe88B82f8a1cc8B0b9d55D253cCBf")
- result = self.eth.get_code(address=address, at_block=EnumsBlockStatus.LATEST)
- self.assertEqual(result,"0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80638c65c81f116100f9578063c05aff5c11610097578063d924393e11610071578063d924393e14610536578063dfefddde1461053e578063f14fcbc814610546578063f897a22b14610563576101a9565b8063c05aff5c146104eb578063c2ca0ac514610511578063c8bc58d91461052e576101a9565b806392166aa4116100d357806392166aa41461047b57806399cdfd4d14610483578063a35bb3a91461048b578063a426e4c814610493576101a9565b80638c65c81f146103f95780638cd221c91461046b5780638da5cb5b14610473576101a9565b80635b28af6d116101665780636d0bf58d116101405780636d0bf58d1461036f578063745921eb14610377578063765339461461039b57806389fb2682146103cd576101a9565b80635b28af6d146102ef5780635b410881146102f75780635eac6239146102ff576101a9565b8063200d2ed2146101ab57806322508e5d146101d75780633501f777146101f45780633b0c3a7c1461020e578063429b62e5146102875780634b0bddd2146102c1575b005b6101b361056b565b604051808260028111156101c357fe5b60ff16815260200191505060405180910390f35b6101a9600480360360208110156101ed57600080fd5b503561057b565b6101fc610b69565b60408051918252519081900360200190f35b6101a96004803603604081101561022457600080fd5b81019060208101813564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184602083028401116401000000008311171561027357600080fd5b9193509150356001600160a01b0316610b6f565b6102ad6004803603602081101561029d57600080fd5b50356001600160a01b0316610e43565b604080519115158252519081900360200190f35b6101a9600480360360408110156102d757600080fd5b506001600160a01b0381351690602001351515610e58565b6101fc610ed4565b6102ad610eda565b6101a96004803603602081101561031557600080fd5b81019060208101813564010000000081111561033057600080fd5b82018360208201111561034257600080fd5b8035906020019184602083028401116401000000008311171561036457600080fd5b509092509050610eea565b6101fc611502565b61037f611508565b604080516001600160a01b039092168252519081900360200190f35b6101a9600480360360608110156103b157600080fd5b50803590602081013590604001356001600160a01b0316611517565b6101fc600480360360408110156103e357600080fd5b50803590602001356001600160a01b0316611a84565b6104166004803603602081101561040f57600080fd5b5035611ab1565b6040805198895260208901979097528787019590955260608701939093526001600160801b0391821660808701521660a085015266ffffffffffffff1660c0840152151560e083015251908190036101000190f35b6101fc611b10565b61037f611b16565b6101a9611b25565b6101fc611c10565b6101a9611c94565b6104b6600480360360408110156104a957600080fd5b5080359060200135611db0565b6040805195151586526001600160a01b0390941660208601528484019290925260608401526080830152519081900360a00190f35b6101a96004803603602081101561050157600080fd5b50356001600160a01b0316611e81565b6101a96004803603602081101561052757600080fd5b5035611fc2565b6101a96123bd565b6101a96124b9565b6101fc612702565b6101a96004803603602081101561055c57600080fd5b5035612708565b61037f61284a565b601154600160a01b900460ff1681565b6002601154600160a01b900460ff16600281111561059557fe5b146105de5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b600b54600019016105ed6135f4565b506000818152600a6020908152604091829020825161010081018452815481526001820154928101929092526002810154928201929092526003820154606082015260048201546001600160801b0380821660808401819052600160801b9092041660a083015260059092015466ffffffffffffff811660c0830152600160381b900460ff16151560e0820152906106e65760118054600160a01b60ff0219169055610e104201600f5560c08101516040805184815266ffffffffffffff909216602083015280517f34fa627446f032cedc60a5521c4a8fbdd28f3ce106d8c6f6c17322ada873cebb9281900390910190a15050610b66565b60a081015160808201516001600160801b0391821685019116811115610716575060808101516001600160801b03165b61071e613656565b61072b8360600151612859565b9050610735613675565b61074b8460c0015166ffffffffffffff16612906565b60a08501519091506000906001016001600160801b03165b848111610913576000878152600a60209081526040808320848452600701909152902054600160a81b900466ffffffffffffff168061087b576107a4613656565b6000898152600a60209081526040808320868452600801909152902080546001909101546107d391908761296a565b905060005b600a8110156108745760008282600a81106107ef57fe5b60200201519050801561086b57808883600a811061080957fe5b602002018051909101905260019550600282101561086b57604080518c81526020810187905260018401818301526060810183905290517fed3e993150009d92ad8e13c907a93c9cee21fa0f33be6bb017ef7d0b54eb44b99181900360800190a15b506001016107d8565b505061090a565b60006108908266ffffffffffffff1686612af9565b90508015610908578560018203600a81106108a757fe5b60200201805160019081019091529350600381101561090857604080518a8152602081018590528082018390526001606082015290517fed3e993150009d92ad8e13c907a93c9cee21fa0f33be6bb017ef7d0b54eb44b99181900360800190a15b505b50600101610763565b506001600160801b0380851660a0870181905260808701519091161415610b0e576000805b6008811015610972576002816008811061094e57fe5b01548582600201600a811061095f57fe5b6020020151029190910190600101610938565b508061097c611c10565b10156109ca5760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600c54818110156109dc5760006109e0565b8181035b855160208701519192506127106114dc84028190049261029485029190910491908115610a1657818481610a1057fe5b04610a19565b60005b60208c01528015610a3357808381610a2d57fe5b04610a36565b60005b60408c0181905260208c015183029082028701018015610a5957600d8054820190555b60208c015115610a7d576020808d015160008f8152600a9092526040909120600101555b60408c015115610aa0576040808d015160008f8152600a60205291909120600201555b60118054600160a01b60ff0219169055610e10420163ffffffff16600f5560c08c0151604080518f815266ffffffffffffff909216602083015280517f34fa627446f032cedc60a5521c4a8fbdd28f3ce106d8c6f6c17322ada873cebb9281900390910190a1505050505050505b8015610b3057610b1d83612cb4565b6000878152600a60205260409020600301555b5050505060a001516000918252600a602052604090912060040180546001600160801b03928316600160801b0292169190911790555b50565b600e5481565b60115460408051600160e01b6323b872dd028152336004820152306024820152622dc6c0850260448201819052915185936001600160a01b0316916323b872dd9160648083019260209291908290030181600087803b158015610bd157600080fd5b505af1158015610be5573d6000803e3d6000fd5b505050506040513d6020811015610bfb57600080fd5b5051610c3b57604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60006001600160a01b0384163314610c535783610c56565b60005b600b546000818152600a602052604081206004015492935090916001600160801b0316905b85811015610d8c576000898983818110610c9157fe5b905060200201359050610ca381612d38565b6040805160608082018352600080835233602080850182815266ffffffffffffff8881168789019081528c8652600a845288862060019c909c016001600160801b0381168088526007909d01855295899020975188549351915160ff1990941690151517610100600160a81b0319166101006001600160a01b039283160217600160a81b600160e01b031916600160a81b93909216929092021790955585518a815290810198909852928916878501529251929591927ff152feb5fe7641aae5c7f8e8187c26eef1a9d970f7c3794ac442f0842282d93f9281900390910190a250600101610c7b565b506000828152600a6020526040902060040180546001600160801b0319166001600160801b0383161790556010546001600160a01b03166360b0b0f0612710610bb8870204856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b158015610e2157600080fd5b505af1158015610e35573d6000803e3d6000fd5b505050505050505050505050565b60016020526000908152604090205460ff1681565b6000546001600160a01b03163314610ea95760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1037bbb732b902604482015290519081900360640190fd5b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b600f5481565b601154600160a81b900460ff1681565b60028106158015610efc575060028110155b610f505760408051600160e51b62461bcd02815260206004820152600e60248201527f696e76616c6964206c656e677468000000000000000000000000000000000000604482015290519081900360640190fd5b600082826000818110610f5f57fe5b602090810292909201356000818152600a90935260409092206004015491925050600160801b81046001600160801b03908116911614610fdd5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000818152600a6020526040812081906007018186866001818110610ffe57fe5b90506020020135815260200190815260200160002060000160019054906101000a90046001600160a01b03169050611034613675565b6000848152600a60205260409020600501546110589066ffffffffffffff16612906565b905060005b858110156113d35786868281811061107157fe5b90506020020135851461112f5786868281811061108a57fe5b602090810292909201356000818152600a90935260409092206004015491965050600160801b81046001600160801b039081169116146111085760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000858152600a602052604090206005015461112c9066ffffffffffffff16612906565b91505b600087878360010181811061114057fe5b9050602002013590506111516136b2565b506000868152600a602090815260408083208484526007018252918290208251606081018452905460ff8116151580835261010082046001600160a01b031693830193909352600160a81b900466ffffffffffffff1692810192909252806111c4575060208101516001600160a01b0316155b806111e5575080602001516001600160a01b0316856001600160a01b031614155b156111f15750506113cb565b6000816040015166ffffffffffffff16600014156112e057611211613656565b6000898152600a602090815260408083208784526008019091529020805460019091015461124091908861296a565b905060015b600a81116112d95760008260018303600a811061125e57fe5b6020020151905080156112d05781600114156112905760008b8152600a602052604090206001015493909301926112d0565b81600214156112b75760008b8152600a6020526040902060020154810293909301926112d0565b80600260038403600881106112c857fe5b015402840193505b50600101611245565b505061135c565b60006112f9836040015166ffffffffffffff1687612af9565b9050806001141561131d576000898152600a6020526040902060010154915061135a565b806002141561133f576000898152600a6020526040902060020154915061135a565b801561135a576002600382036008811061135557fe5b015491505b505b80156113c7576000888152600a60209081526040808320868452600701825291829020805460ff1916600117905581518a81529081018590528151988301987f179780be10c742bdbc92cd0af59e83edeb067cd1954ef4d647827d8504c7c2ca929181900390910190a15b5050505b60020161105d565b506000831161141a5760408051600160e51b62461bcd0281526020600482015260086024820152600160c01b676e6f207072697a6502604482015290519081900360640190fd5b82600d54101561146c5760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600d8054849003905560115460408051600160e01b63a9059cbb0281526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156114ce57600080fd5b505af11580156114e2573d6000803e3d6000fd5b505050506040513d60208110156114f857600080fd5b5050505050505050565b600d5481565b6010546001600160a01b031681565b60f883901c60ff60f085901c1660068210801590611536575060268211155b61158a5760408051600160e51b62461bcd02815260206004820152601260248201527f696e76616c6964207a6f6e6531436f756e740000000000000000000000000000604482015290519081900360640190fd5b6001811015801561159c575060088111155b6115f05760408051600160e51b62461bcd02815260206004820152601260248201527f696e76616c6964207a6f6e6532436f756e740000000000000000000000000000604482015290519081900360640190fd5b6000816115fe846006612fa7565b60115460408051600160e01b6323b872dd02815233600482015230602482015292909302622dc6c081026044840181905293519094506001600160a01b03909116916323b872dd9160648083019260209291908290030181600087803b15801561166757600080fd5b505af115801561167b573d6000803e3d6000fd5b505050506040513d602081101561169157600080fd5b50516116d157604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60ff60e888901c1660018110156117205760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b6002840160031b611734898360188461303f565b9150600882111561177d5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b8060f80389901c60ff16915060018210156117d05760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b600385601e0387116117e7578587016002016117ea565b60205b901b90506118018983600388600301901b8461303f565b915084601e0386111561183057600385601e880301901b905061182d8883600388600301901b8461303f565b91505b60268211156118775760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b60006001600160a01b038816331461188f5787611892565b60005b600b546000818152600a60209081526040808320600481015482516060810184528581523381860190815281850187815260016001600160801b03948516019384168852600785018752858820925183549251915160ff1990931690151517610100600160a81b0319166101006001600160a01b039092169190910217600160a81b600160e01b031916600160a81b66ffffffffffffff9092169190910217905560089091019092529091208d9055919250908a15611977576000828152600a602090815260408083206001600160801b038516845260080190915290206001018b90555b604080518381526001600160801b03831660208201526001600160a01b03851681830152905133917ff152feb5fe7641aae5c7f8e8187c26eef1a9d970f7c3794ac442f0842282d93f919081900360600190a26000828152600a6020526040902060040180546001600160801b0319166001600160801b0383161790556010546001600160a01b03166360b0b0f0612710610bb8890204856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b158015611a5e57600080fd5b505af1158015611a72573d6000803e3d6000fd5b50505050505050505050505050505050565b6000828152600a602090815260408083206001600160a01b03851684526006019091529020545b92915050565b600a6020526000908152604090208054600182015460028301546003840154600485015460059095015493949293919290916001600160801b0380831692600160801b9004169066ffffffffffffff811690600160381b900460ff1688565b600b5481565b6000546001600160a01b031681565b6010546001600160a01b0316611b855760408051600160e51b62461bcd02815260206004820152601260248201527f66756e646572506f6f6c206e6f74207365740000000000000000000000000000604482015290519081900360640190fd5b60115460105460408051600160e01b63095ea7b30281526001600160a01b03928316600482015260001960248201529051919092169163095ea7b39160448083019260209291908290030181600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b505050506040513d6020811015611c0c57600080fd5b5050565b600d5460115460408051600160e01b6370a082310281523060048201529051600093926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c6257600080fd5b505afa158015611c76573d6000803e3d6000fd5b505050506040513d6020811015611c8c57600080fd5b505103905090565b601154600090600160a81b900460ff16611cb457600e54611c5c01611cbb565b603c600e54015b9050804211611d065760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b600b54600019016000908152600a6020526040902054611d25906130b0565b601154600160a81b900460ff16610b665760118054600160a81b60ff021916600160a81b17905560105460408051600160e11b63419ab82902815290516001600160a01b039092169163833570529160048082019260009290919082900301818387803b158015611d9557600080fd5b505af1158015611da9573d6000803e3d6000fd5b5050505050565b6000806000806000611dc06136b2565b506000878152600a602090815260408083208984526007018252918290208251606081018452905460ff81161515825261010081046001600160a01b031692820192909252600160a81b90910466ffffffffffffff1691810191909152611e256136d2565b506000978852600a60209081526040808a20988a526008909801815297879020875180890189528154808252600190920154908a0181905282519983015192909801519899919866ffffffffffffff1697909650945092505050565b6000546001600160a01b03163314611ed25760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1037bbb732b902604482015290519081900360640190fd5b6010546001600160a01b031615611f245760408051600160e51b62461bcd02815260206004820152600b6024820152600160aa1b6a185b1c9958591e481cd95d02604482015290519081900360640190fd5b601080546001600160a01b0319166001600160a01b0383811691821790925560115460408051600160e01b63095ea7b3028152600481019390935260001960248401525192169163095ea7b3916044808201926020929091908290030181600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b505050506040513d6020811015611fbd57600080fd5b505050565b6001601154600160a01b900460ff166002811115611fdc57fe5b146120255760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b600b54600019016120353361318b565b801561204b5750601154600160a81b900460ff16155b1561219157603c600e5401421161209e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b6000818152600a602090815260408083208380526006019091529020546120c4836131c2565b1461210d5760408051600160e51b62461bcd02815260206004820152600e6024820152600160921b6d1a5b9d985b1a59081cd958dc995d02604482015290519081900360640190fd5b6000818152600a60208181526040808420848052600681018352908420849055928490525254820161213e816130b0565b6000828152600a6020908152604080832084905580518581529182019290925281517f18e3a2a1539c4d2325524f2c652bd26fea78b54a5861212876952caf2e00582b929181900390910190a1506122b4565b600e544211156121dd5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b6000818152600a60209081526040808320338452600601909152902054612203836131c2565b1461224c5760408051600160e51b62461bcd02815260206004820152600e6024820152600160921b6d1a5b9d985b1a59081cd958dc995d02604482015290519081900360640190fd5b6000818152600a6020818152604080842033808652600682018452828620869055948690529282528254860190925581518481529081019290925280517f18e3a2a1539c4d2325524f2c652bd26fea78b54a5861212876952caf2e00582b9281900390910190a15b6000818152600a6020526040902060050154600160381b900460ff16611c0c576000818152600a60209081526040808320600501805467ff000000000000001916600160381b1790556011548151600160e01b63a9059cbb0281523360048201526305f5e100602482015291516001600160a01b039091169363a9059cbb93604480850194919392918390030190829087803b15801561235357600080fd5b505af1158015612367573d6000803e3d6000fd5b505050506040513d602081101561237d57600080fd5b50506040805182815233602082015281517fc7ad212fc37b0fda8af53154f4fc8674770b9d813b1863178c39c4ed2128edc1929181900390910190a15050565b601154600160a81b900460ff166123da57611c20600f54016123de565b600f545b42116124265760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b61242e6131e6565b601154600160a81b900460ff166124b75760118054600160a81b60ff021916600160a81b17905560105460408051600160e11b63419ab82902815290516001600160a01b039092169163833570529160048082019260009290919082900301818387803b15801561249e57600080fd5b505af11580156124b2573d6000803e3d6000fd5b505050505b565b6124c23361318b565b6125055760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1030b236b4b702604482015290519081900360640190fd5b601154600160a81b900460ff16156125675760408051600160e51b62461bcd02815260206004820152600f60248201527f6d6574686f642064697361626c65640000000000000000000000000000000000604482015290519081900360640190fd5b6001601154600160a01b900460ff16600281111561258157fe5b146125ca5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b60115460408051600160e01b6323b872dd0281523360048201523060248201526402540be400604482015290516001600160a01b03909216916323b872dd916064818101926020929091908290030181600087803b15801561262b57600080fd5b505af115801561263f573d6000803e3d6000fd5b505050506040513d602081101561265557600080fd5b505161269557604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60118054600160a01b60ff0219169055600b80546000190190819055610e10420163ffffffff16600f556000818152600a6020526040902060050154600160381b900460ff1615610b66576000908152600a60205260409020600501805467ff0000000000000019169055565b600c5481565b6127113361318b565b80156127275750601154600160a81b900460ff16155b156127e557600f5442116127775760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b61277f6131e6565b600b80546000199081016000908152600a602090815260408083208380526006018252808320869055935484519301835282015281517f775cbcccd7fe28145ecb9139488663063065c5a215ba96419500f1bb1217661e929181900390910190a1610b66565b600b80546000908152600a60209081526040808320338085526006909101835292819020859055925483519081529081019190915281517f775cbcccd7fe28145ecb9139488663063065c5a215ba96419500f1bb1217661e929181900390910190a150565b6011546001600160a01b031681565b612861613656565b60405180610140016040528060f084901c61ffff16815260200160e084901c61ffff16815260200160d084901c61ffff16815260200160c084901c61ffff16815260200160a084901c63ffffffff168152602001608084901c63ffffffff168152602001606084901c63ffffffff168152602001604084901c63ffffffff168152602001602084901c63ffffffff1681526020018363ffffffff168152509050919050565b61290e613675565b612916613675565b60ff80841660c0830152600884901c811660a0830152601084901c81166080830152601884901c81166060830152602084811c82166040840152602885901c821690830152603084901c1681529050919050565b612972613656565b61297a613656565b60c083015160f886901c9060ff60f088901c16906002820160031b600060105b828110156129c85760ff60f88290038c901c16848114156129bf5760019250506129c8565b5060080161299a565b5060006129d886868d8d8d6132f6565b90508015612aea578185036001831415612a02576129f98288036005612fa7565b82026101208901525b6001821115612ae8578260011415612a3357612a218288036004612fa7565b612a2c836002612fa7565b0260e08901525b6002821115612ae8576000612a4b8389036003612fa7565b612a56846003612fa7565b0284810260c08b01528281026101008b015290506003831115612ae657612a808389036002612fa7565b612a8b846004612fa7565b0284810260808b015282810260a08b015290506004831115612ae657612ab48389036001612fa7565b612abf846005612fa7565b0284810260408b015282810260608b015290506005831115612ae657838952602089018290525b505b505b50949998505050505050505050565b8051602082015160408301516060840151608085015160a08601516000958695909490939092909160085b60308111612b8e5760ff8b821c1684811015612b625787811480612b4757508681145b80612b5157508581145b15612b5d578860010198505b612b85565b84811480612b6f57508381145b80612b7957508281145b15612b85578860010198505b50600801612b24565b5086612ba4576000975050505050505050611aab565b8860c001518a60ff161415612c40578660011415612bcc57600a975050505050505050611aab565b8660021415612be5576008975050505050505050611aab565b8660031415612bfe576007975050505050505050611aab565b8660041415612c17576005975050505050505050611aab565b8660051415612c30576003975050505050505050611aab565b6001975050505050505050611aab565b6003871015612c59576000975050505050505050611aab565b8660031415612c72576009975050505050505050611aab565b8660041415612c8b576006975050505050505050611aab565b8660051415612ca4576004975050505050505050611aab565b6002975050505050505050611aab565b61012081015160009060208360086020020151901b60408460076020020151901b60608560066020020151901b60808660056020020151901b60a08760046020020151901b60c08860036020020151901b60d08960026020020151901b60e08a60016020020151901b60f08b60006020020151901b17171717171717171792915050565b60ff603082901c811690602883901c811690602084901c811690601885901c811690601086901c811690600887901c811690871660018110801590612d7e575060088111155b612dc05760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b6026821115612e075760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b828211612e4c5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b838311612e915760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b848411612ed65760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b858511612f1b5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b868611612f605760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b60018710156114f85760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b600081831015612fb957506000611aab565b81831415612fc957506001611aab565b60008284038310612fdc57828403612fde565b825b90508060011415612ff25783915050611aab565b80840360018101906002015b8581116130115790810290600101612ffe565b50600160025b83811161302a5790810290600101613017565b5080828161303457fe5b049350505050611aab565b600083835b838110156130a65760ff60f882900388901c1682811161309c5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b9150600801613044565b5095945050505050565b60118054600160a01b60ff021916600160a11b1790556130ce6136ec565b6130d782613452565b905060006130e98360060160086135d9565b60010190508060088360056020020151901b60108460046020020151901b60188560036020020151901b60208660026006811061312257fe5b6020020151901b60288760016020020151901b60308860006020020151901b171717171717600a60006001600b5403815260200190815260200160002060050160006101000a81548166ffffffffffffff021916908366ffffffffffffff160217905550505050565b6001600160a01b03811660009081526001602052604081205460ff1680611aab5750506000546001600160a01b0390811691161490565b60408051602080820193909352815180820384018152908201909152805191012090565b6000601154600160a01b900460ff16600281111561320057fe5b146132495760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000613253611c10565b90506305f5e1008110156132a95760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600b80546000908152600a6020526040902080546000194301400190558054600101905560118054600160a01b60ff021916600160a01b1790554260f001600e556305f5e0ff1901600c55565b8051602082015160408301516060840151608085015160a086015160009586959094909390929091866003601e8e90038f11613337578d8f0160020161333a565b60205b901b905060028d0160031b5b818110156133b55760ff60f88290038e901c1685811015613389578881148061336e57508781145b8061337857508681145b15613384578960010199505b6133ac565b8581148061339657508481145b806133a057508381145b156133ac578960010199505b50600801613346565b508c601e038e1115613440575060088d8d01601d19010260005b8181101561343e5760ff60f88290038d901c168581101561341257888114806133f757508781145b8061340157508681145b1561340d578960010199505b613435565b8581148061341f57508481145b8061342957508381145b15613435578960010199505b506008016133cf565b505b50959c9b505050505050505050505050565b61345a6136ec565b6134626136ec565b61346a61370a565b60005b600681101561350457600081613488838801846026036135d9565b019050600083836026811061349957fe5b6020020151905060008483602681106134ae57fe5b6020020151905081156134c157816134c6565b836001015b8584602681106134d257fe5b602002015280156134e357806134e8565b826001015b8585602681106134f457fe5b602002015250505060010161346d565b5060005b600681101561353b5781816026811061351d57fe5b602002015183826006811061352e57fe5b6020020152600101613508565b5060015b60068110156135d057600083826006811061355657fe5b60200201519050815b60008111801561358157508185600183036006811061357a57fe5b6020020151115b156135b45784600182036006811061359557fe5b60200201518582600681106135a657fe5b60200201526000190161355f565b818582600681106135c157fe5b6020020152505060010161353f565b50909392505050565b6000816135e5846131c2565b816135ec57fe5b069392505050565b6040518061010001604052806000815260200160008152602001600081526020016000815260200160006001600160801b0316815260200160006001600160801b03168152602001600066ffffffffffffff1681526020016000151581525090565b604051806101400160405280600a906020820280388339509192915050565b6040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b604051806040016040528060008152602001600081525090565b6040518060c001604052806006906020820280388339509192915050565b604051806104c00160405280602690602082028038833950919291505056fe696e73756666696369656e74206d6f6e6579206f72206e6f7420617070726f766564696e76616c6964206e756d626572000000000000000000000000000000000000a165627a7a72305820b1048538cbbafc97df106db92d6a5ebccd84e57642875c04cd1d4acf5a6046100029")
-
- #TODO: TEST signature later
- def test_get_sign(self):
- address = Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- message = "0x000000000"
- rpc = in3.eth.account.sign(address=address, message=message)
- print(rpc)
-
- #TODO: test it later
- def test_send_transaction(self):
- _from = Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- transaction = Transaction(_from=_from)
- rpc = in3.client.send_transaction(transaction=transaction)
- print(rpc)
-
- #TODO: test it later
- def test_send_raw_transaction(self):
- data = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
- rpc = self.eth.send_raw_transaction(data=data )
- print(rpc)
-
- #TODO: test it later
- def test_call(self):
- _from = Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- transaction = Transaction(_from=_from)
- rpc = self.eth.call(transaction=transaction)
- print(rpc)
-
- #TODO: don't work
- def test_estimate_gas(self):
- _from = Address("0x9e52ee6acd6e7f55e860844d487556f8cbe2baee")
- to = Address("0x9e24916a735ffd9dad24bc789e146737d4b4037c")
- transaction = Transaction(_from=_from, to=to)
- transaction.data = "0x3852a97b0000000000000000000000000000000000000000000000000000000000000000"
- rpc = self.eth.estimate_gas(transaction=transaction)
- print(rpc)
-
- def test_get_block_by_hash(self):
- hash = Hash("0xa69fd32d87d4cab4041391ae11a9375ac647894b689041f97056a6109e0352e6")
- rpc = self.eth.get_block_by_hash(hash=hash, get_full_block=False)
- self.assertEqual(rpc.number.to_int(), 15124817)
-
-
- def test_get_block_by_number(self):
- number = IN3Number(15124817)
- rpc = self.eth.get_block_by_number(block_number=number)
- self.assertEqual(rpc.number.to_int(), 15124817 )
-
- # It's returning null
- def test_get_transaction_by_hash(self):
- # https://etherscan.io/tx/0x4214540f465a9e201de4692715468e2f06c39f70db6dca32fdaecea16a8d0b16
- hash = Hash("0x4214540f465a9e201de4692715468e2f06c39f70db6dca32fdaecea16a8d0b16")
- rpc = self.eth.get_transaction_by_hash(hash=hash)
- self.assertEqual(rpc.result["from"], "0x78a087fcf440315b843632cfd6fde6e5adccc2c2")
-
- # TODO: error
- def test_get_transaction_by_block_hash_and_index(self):
- hash = Hash("0x4a096b467aee064eb622d3db1559f4478d90c473c9e2ea9653b26935e564d83c")
- index = IN3Number(3)
- rpc = self.eth.get_transaction_by_block_hash_and_index(block_hash=hash,index=index)
- print(rpc)
-
- # TODO: error
- def test_get_transaction_by_block_number_and_index(self):
- # block_number= EnumsBlockStatus.LATEST
- block_number= IN3Number(8979548)
- index = IN3Number(2)
- rpc= self.eth.get_transaction_by_block_number_and_index(block_number=block_number, index=index)
- print(rpc)
-
- def test_get_transaction_receipt(self):
- hash = Hash("0xe8222e785eb3279b75bb8eb56457de5fb4def32f440b71bc5cc72b999dee4ab4")
- result = self.eth.get_transaction_receipt(hash=hash)
- self.assertIsNotNone(result.result["blockHash"])
-
- #TODO: error
- def test_pending_transactions(self):
- result = self.eth.pending_transactions()
- print(result)
-
- # TODO: to test it later
- def test_get_uncle_by_block_hash_and_index(self):
- # check later for the uncle by block
- hash = Hash("0xe24d326104e929331204774af3dba4dd6ceb67d0f16748a08ccd238c462354ca")
- index = IN3Number("0")
- result = self.eth.get_uncle_by_block_hash_and_index(block_hash=hash,index=index)
- print(result)
-
- # TODO: to test it later
- def test_get_uncle_by_block_number_and_index(self):
- # check later for the uncle by block
- block_number = IN3Number("0xe24d326104e929331204774af3dba4dd6ceb67d0f16748a08ccd238c462354ca")
- index = IN3Number("0")
- result = self.eth.get_uncle_by_block_number_and_index(block_number=block_number,index=index)
- print(result)
-
- #TODO: validate it later but it's working, besides that we got a message of error
- def test_new_filter(self):
- filter = Filter(fromBlock=EnumsBlockStatus.LATEST, toBlock=EnumsBlockStatus.EARLIEST, address=Address("0xdcf7baece1802d21a8226c013f7be99db5941bea"))
- response = self.eth.new_filter(filter=filter)
- print(response)
- self.assertEqual(response.result, "0x1")
-
- #TODO: new block filter error
- def test_new_block_filter(self):
- filter = self.eth.new_block_filter()
- print(filter)
-
- #TODO: new pending
- def test_new_pending_transaction_filter(self):
- filter= self.eth.new_pending_transaction_filter()
- print(filter)
-
- def test_uninstall_filter(self):
- filter = Filter(fromBlock=EnumsBlockStatus.LATEST, toBlock=EnumsBlockStatus.EARLIEST, address=Address("0xdcf7baece1802d21a8226c013f7be99db5941bea"))
- response = self.eth.new_filter(filter=filter)
- filter_id = IN3Number(response.result)
- result = self.eth.uninstall_filter(filter_id=filter_id)
- print(result)
-
- #TODO: to add filter test
- def test_get_filter_logs(self):
- filter_id = IN3Number(1)
- result = self.eth.get_filter_logs(filter_id=filter_id)
- print(result)
-
- #TODO: to add filter test
- def test_get_logs(self):
- filter = Filter(fromBlock=EnumsBlockStatus.LATEST, toBlock=EnumsBlockStatus.EARLIEST, address=Address("0xdcf7baece1802d21a8226c013f7be99db5941bea") )
- self.eth.get_logs(filter=filter)
-
-
-
-
-
-
diff --git a/python/__tests__/src/in3/in3.py b/python/__tests__/src/in3/in3.py
deleted file mode 100644
index afcec0df7..000000000
--- a/python/__tests__/src/in3/in3.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from in3py.in3.in3 import IN3
-from in3py.model.in3_model import IN3Config
-from in3py.model.in3_model import RPCRequest, Address, ChainsDefinitions
-from in3py.enums.in3 import EnumIn3Methods
-from in3py.enums.in3 import EnumsEthCall
-
-from in3py.runner.in3_runner import In3Runner
-from in3py.utils.utils import rpc_to_string
-
-from unittest import TestCase
-
-import json
-
-import in3.client
-
-
-class In3Test(TestCase):
-
- def setUp(self):
- self.in3 = IN3()
-
- def test_config(self):
- config = IN3Config()
- config.chainId = ChainsDefinitions.KOVAN.value
- result = in3.client.config(in3_config=config)
- self.assertTrue(result.result)
-
- def test_address(self):
- address = Address("0x1fe2e9bf29aa1938859af64c413361227d04059a")
- checked = in3.client.checksum_address(address=address, chain=False)
- self.assertEqual("0x1Fe2E9bf29aa1938859Af64C413361227d04059a", checked.result)
- print(checked)
-
- def test_abi_encode(self):
- encoded = in3.client.abi_encode("getBalance(address)", ["0x1234567890123456789012345678901234567890"])
- self.assertEqual("0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890",encoded.result)
-
- def test_abi_decode(self):
- decoded = in3.client.abi_decode("(address,uint256)", "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005")
- self.assertEqual(decoded.result[0],"0x1234567890123456789012345678901234567890")
-
diff --git a/python/ci.yml b/python/ci.yml
index dffdae3f2..dade8075d 100644
--- a/python/ci.yml
+++ b/python/ci.yml
@@ -1,3 +1,17 @@
+.only_python:
+ rules:
+ - changes:
+ - python/**/*
+ - 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"'
+
+# This template should be used for jobs to run during deployment only
+.only_deploy:
+ rules:
+ - if: '$CI_COMMIT_TAG =~ /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/'
+ when: manual
+
python:
image: python
stage: bindings
@@ -6,18 +20,21 @@ python:
- win_jni
- gcc8
- arm_jni
+ - gcc8-x86
tags:
- short-jobs
script:
- cp mac_build/lib/libin3.dylib python/in3/libin3/shared/libin3.x64.dylib
- - cp win_jni/lib/libin3.so python/in3/libin3/shared/in3.x64.dll
+ - cp win_jni/lib/libin3.so python/in3/libin3/shared/libin3.x64.dll
- cp x64_build/lib/libin3.so python/in3/libin3/shared/libin3.x64.so
+ - cp x86_build/lib/libin3.so python/in3/libin3/shared/libin3.x86.so
- cp arm_jni_build/lib/libin3.so python/in3/libin3/shared/libin3.arm7.so
- - mv python python_multilib
- - cd python_multilib
+ - cd python
- pip3 install -r requirements.txt
- ./generate_docs.sh
- rm -rf docs/_build docs/build_examples.md_
+ - cd ..
+ - mv python python_multilib
artifacts:
paths:
- python_multilib
@@ -25,6 +42,7 @@ python:
python_arm:
allow_failure: true
image: python
+ extends: .only_python
needs:
- python
stage: python
@@ -39,6 +57,7 @@ python_arm:
- arm
python_win:
+ extends: .only_python
allow_failure: true
needs:
- python
@@ -54,6 +73,7 @@ python_win:
- windows
python_macos:
+ extends: .only_python
allow_failure: true
needs:
- python
@@ -69,9 +89,9 @@ python_macos:
- mac-mini-runner
python_linux:
+ extends: .only_python
needs:
- python
- allow_failure: true
image: python
stage: python
script:
@@ -89,10 +109,7 @@ release_pip:
image: docker.slock.it/build-images/python-dev-image:latest
tags:
- short-jobs
- only:
- - /^v[0-9]+.[0-9]+.[0-9]+(\-RC[0-9]+)?$/
- except:
- - branches
+ extends: .only_deploy
needs:
- mac_os
- python
@@ -100,9 +117,7 @@ release_pip:
- cp python_multilib/in3/libin3/shared/* python/in3/libin3/shared/
- export version=${CI_COMMIT_TAG}
- export download_url=https://github.com/slockit/in3-c/releases/download/${CI_COMMIT_TAG}/in3_${CI_COMMIT_TAG}_mac.tar.gz
+ - sed -i "s/version = environ.*/version = \"$version\"/" python/setup.py
- cd python
- cp $pypirc ~/.pypirc
- ./publish.sh
- artifacts:
- paths:
- - in3-pip
diff --git a/python/docs/2_examples.md b/python/docs/2_examples.md
deleted file mode 100644
index e45111d7c..000000000
--- a/python/docs/2_examples.md
+++ /dev/null
@@ -1,149 +0,0 @@
-## Examples
-
-### block_number
-
-source : [in3-c/python/examples/block_number.py](https://github.com/slockit/in3-c/blob/master/python/examples/block_number.py)
-
-
-
-```python
-import in3
-
-
-print('\nEthereum Main Network')
-client = in3.Client()
-latest_block = client.eth.block_number()
-gas_price = client.eth.gas_price()
-print('Latest BN: {}\nGas Price: {} Wei'.format(latest_block, gas_price))
-
-print('\nEthereum Kovan Test Network')
-client = in3.Client('kovan')
-latest_block = client.eth.block_number()
-gas_price = client.eth.gas_price()
-print('Latest BN: {}\nGas Price: {} Wei'.format(latest_block, gas_price))
-
-print('\nEthereum Goerli Test Network')
-client = in3.Client('goerli')
-latest_block = client.eth.block_number()
-gas_price = client.eth.gas_price()
-print('Latest BN: {}\nGas Price: {} Wei'.format(latest_block, gas_price))
-
-# Results Example
-"""
-Ethereum Main Network
-Latest BN: 9801135
-Gas Price: 2000000000 Wei
-
-Ethereum Kovan Test Network
-Latest BN: 17713464
-Gas Price: 6000000000 Wei
-
-Ethereum Goerli Test Network
-Latest BN: 2460853
-Gas Price: 4610612736 Wei
-"""
-```
-
-### in3_config
-
-source : [in3-c/python/examples/in3_config.py](https://github.com/slockit/in3-c/blob/master/python/examples/in3_config.py)
-
-
-
-```python
-import in3
-
-if __name__ == '__main__':
-
- print('\nEthereum Goerli Test Network')
- goerli_cfg = in3.ClientConfig(chainId=str(in3.Chain.GOERLI), signatureCount=3, timeout=10000)
- client = in3.Client(goerli_cfg)
- node_list = client.node_list()
- print('\nIncubed Registry:')
- print('\ttotal servers:', node_list.totalServers)
- print('\tlast updated in block:', node_list.lastBlockNumber)
- print('\tregistry ID:', node_list.registryId)
- print('\tcontract address:', node_list.contract)
- print('\nNodes Registered:\n')
- for node in node_list.nodes:
- print('\turl:', node.url)
- print('\tdeposit:', node.deposit)
- print('\tweight:', node.weight)
- print('\tregistered in block:', node.registerTime)
- print('\n')
-
-# Results Example
-"""
-Ethereum Goerli Test Network
-
-Incubed Registry:
- total servers: 7
- last updated in block: 2320627
- registry ID: 0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea
- contract address: 0x5f51e413581dd76759e9eed51e63d14c8d1379c8
-
-Nodes Registered:
-
- url: https://in3-v2.slock.it/goerli/nd-1
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227711
-
-
- url: https://in3-v2.slock.it/goerli/nd-2
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227741
-
-
- url: https://in3-v2.slock.it/goerli/nd-3
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227801
-
-
- url: https://in3-v2.slock.it/goerli/nd-4
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227831
-
-
- url: https://in3-v2.slock.it/goerli/nd-5
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227876
-
-
- url: https://tincubeth.komputing.org/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578947320
-
-
- url: https://h5l45fkzz7oc3gmb.onion/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578954071
-"""
-```
-
-
-
-## Running the examples
-
-To run an example, you need to install in3 first:
-```sh
-pip install in3
-```
-
-Copy one of the examples, or both and paste into a file, i.e. `example.py`:
-
-`MacOS`
-```sh
-pbpaste > example.py
-```
-
-Execute the example with python:
-```
-python example.py
-```
diff --git a/python/docs/build_examples.md b/python/docs/build_examples.md
index 0421ddf62..aea5db208 100644
--- a/python/docs/build_examples.md
+++ b/python/docs/build_examples.md
@@ -1,13 +1,13 @@
-
### Running the examples
To run an example, you need to install in3 first:
```sh
pip install in3
```
+This will install the library system-wide. Please consider using `virtualenv` or `pipenv` for a project-wide install.
-Copy one of the examples, or both and paste into a file, i.e. `example.py`:
+Then copy one of the examples and paste into a file, i.e. `example.py`:
`MacOS`
```sh
diff --git a/python/docs/documentation.md b/python/docs/documentation.md
index a53ab8f92..a7a8cf11d 100644
--- a/python/docs/documentation.md
+++ b/python/docs/documentation.md
@@ -14,51 +14,61 @@ This library is based on the [C version of Incubed](http://github.com/slockit/in
pip install in3
```
-### In3 Client Standalone
+### In3 Client API
```python
import in3
in3_client = in3.Client()
+# Sends a request to the Incubed Network, that in turn will collect proofs from the Ethereum client,
+# attest and sign the response, then send back to the client, that will verify signatures and proofs.
block_number = in3_client.eth.block_number()
print(block_number) # Mainnet's block number
-in3_client.eth # ethereum module
-in3_client.in3 # in3 module
+in3_client # incubed network api
+in3_client.eth # ethereum api
+in3_client.account # ethereum account api
+in3_client.contract # ethereum smart-contract api
```
### Tests
```bash
-python tests/test_suite.py
+pytest --pylama
```
-### Contributing
-1. Read the index and respect the architecture. For additional packages and files please update the index.
-2. (Optional) Get the latest `libin3.dylib` from the Gitlab Pipeline on the `in-core` project and replace it in `in3/bind` folder.
-3. Write the changes in a new branch, then make a pull request for the `develop` branch when all tests are passing. Be sure to add new tests to the CI.
-
### Index
Explanation of this source code architecture and how it is organized. For more on design-patterns see [here](http://geekswithblogs.net/joycsharp/archive/2012/02/19/design-patterns-for-model.aspx) or on [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
- **in3.__init__.py**: Library entry point, imports organization. Standard for any pipy package.
-- **in3.eth**: Package for Ethereum objects and tools.
-- **in3.eth.account**: Api for managing simple wallets and smart-contracts alike.
-- **in3.eth.api**: Ethereum tools and Domain Objects.
-- **in3.eth.model**: Value Objects for Ethereum.
-- **in3.libin3**: Package for everything related to binding libin3 to python. Libin3 is written in C and can be found [here](https://github.com/slockit/in3-c).
+- **in3.client**: Incubed Client and API.
+- **in3.model**: MVC Model classes for the Incubed client module domain.
+- **in3.transport**: HTTP Transport function and error handling.
+- **in3.wallet**: WiP - Wallet API.
+- **in3.exception**: Custom exceptions.
+- **in3.eth**: Ethereum module.
+- **in3.eth.api**: Ethereum API.
+- **in3.eth.account**: Ethereum accounts.
+- **in3.eth.contract**: Ethereum smart-contracts API.
+- **in3.eth.model**: MVC Model classes for the Ethereum client module domain. Manages serializaation.
+- **in3.eth.factory**: Ethereum Object Factory. Manages deserialization.
+- **in3.libin3**: Module for the libin3 runtime. Libin3 is written in C and can be found [here](https://github.com/slockit/in3-c).
- **in3.libin3.shared**: Native shared libraries for multiple operating systems and platforms.
- **in3.libin3.enum**: Enumerations mapping C definitions to python.
- **in3.libin3.lib_loader**: Bindings using Ctypes.
- **in3.libin3.runtime**: Runtime object, bridging the remote procedure calls to the libin3 instances.
+
## Examples
-### block_number
+### connect_to_ethereum
-source : [in3-c/python/examples/block_number.py](https://github.com/slockit/in3-c/blob/master/python/examples/block_number.py)
+source : [in3-c/python/examples/connect_to_ethereum.py](https://github.com/slockit/in3-c/blob/master/python/examples/connect_to_ethereum.py)
```python
+"""
+Connects to Ethereum and fetches attested information from each chain.
+"""
import in3
@@ -80,7 +90,7 @@ latest_block = client.eth.block_number()
gas_price = client.eth.gas_price()
print('Latest BN: {}\nGas Price: {} Wei'.format(latest_block, gas_price))
-# Results Example
+# Produces
"""
Ethereum Main Network
Latest BN: 9801135
@@ -94,91 +104,284 @@ Ethereum Goerli Test Network
Latest BN: 2460853
Gas Price: 4610612736 Wei
"""
+
```
-### in3_config
+### incubed_network
-source : [in3-c/python/examples/in3_config.py](https://github.com/slockit/in3-c/blob/master/python/examples/in3_config.py)
+source : [in3-c/python/examples/incubed_network.py](https://github.com/slockit/in3-c/blob/master/python/examples/incubed_network.py)
```python
+"""
+Shows Incubed Network Nodes Stats
+"""
import in3
-if __name__ == '__main__':
-
- print('\nEthereum Goerli Test Network')
- goerli_cfg = in3.ClientConfig(chainId=str(in3.Chain.GOERLI), signatureCount=3, timeout=10000)
- client = in3.Client(goerli_cfg)
- node_list = client.node_list()
- print('\nIncubed Registry:')
- print('\ttotal servers:', node_list.totalServers)
- print('\tlast updated in block:', node_list.lastBlockNumber)
- print('\tregistry ID:', node_list.registryId)
- print('\tcontract address:', node_list.contract)
- print('\nNodes Registered:\n')
- for node in node_list.nodes:
- print('\turl:', node.url)
- print('\tdeposit:', node.deposit)
- print('\tweight:', node.weight)
- print('\tregistered in block:', node.registerTime)
- print('\n')
-
-# Results Example
+print('\nEthereum Goerli Test Network')
+client = in3.Client('goerli')
+node_list = client.refresh_node_list()
+print('\nIncubed Registry:')
+print('\ttotal servers:', node_list.totalServers)
+print('\tlast updated in block:', node_list.lastBlockNumber)
+print('\tregistry ID:', node_list.registryId)
+print('\tcontract address:', node_list.contract)
+print('\nNodes Registered:\n')
+for node in node_list.nodes:
+ print('\turl:', node.url)
+ print('\tdeposit:', node.deposit)
+ print('\tweight:', node.weight)
+ print('\tregistered in block:', node.registerTime)
+ print('\n')
+
+# Produces
"""
Ethereum Goerli Test Network
Incubed Registry:
- total servers: 7
- last updated in block: 2320627
- registry ID: 0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea
- contract address: 0x5f51e413581dd76759e9eed51e63d14c8d1379c8
+ total servers: 7
+ last updated in block: 2320627
+ registry ID: 0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea
+ contract address: 0x5f51e413581dd76759e9eed51e63d14c8d1379c8
Nodes Registered:
- url: https://in3-v2.slock.it/goerli/nd-1
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227711
+ url: https://in3-v2.slock.it/goerli/nd-1
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227711
+
+
+ url: https://in3-v2.slock.it/goerli/nd-2
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227741
+
+
+ url: https://in3-v2.slock.it/goerli/nd-3
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227801
+
+
+ url: https://in3-v2.slock.it/goerli/nd-4
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227831
+
+
+ url: https://in3-v2.slock.it/goerli/nd-5
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227876
+
+
+ url: https://tincubeth.komputing.org/
+ deposit: 10000000000000000
+ weight: 1
+ registered in block: 1578947320
+
+
+ url: https://h5l45fkzz7oc3gmb.onion/
+ deposit: 10000000000000000
+ weight: 1
+ registered in block: 1578954071
+"""
+
+```
+
+### resolve_eth_names
+
+source : [in3-c/python/examples/resolve_eth_names.py](https://github.com/slockit/in3-c/blob/master/python/examples/resolve_eth_names.py)
+
- url: https://in3-v2.slock.it/goerli/nd-2
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227741
+```python
+"""
+Resolves ENS domains to Ethereum addresses
+ENS is a smart-contract system that registers and resolves `.eth` domains.
+"""
+import in3
- url: https://in3-v2.slock.it/goerli/nd-3
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227801
+def _print():
+ print('\nAddress for {} @ {}: {}'.format(domain, chain, address))
+ print('Owner for {} @ {}: {}'.format(domain, chain, owner))
- url: https://in3-v2.slock.it/goerli/nd-4
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227831
+# Find ENS for the desired chain or the address of your own ENS resolver. https://docs.ens.domains/ens-deployments
+domain = 'depraz.eth'
+print('\nEthereum Name Service')
- url: https://in3-v2.slock.it/goerli/nd-5
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227876
+# Instantiate In3 Client for Goerli
+chain = 'goerli'
+client = in3.Client(chain)
+address = client.ens_address(domain)
+# Instantiate In3 Client for Mainnet
+chain = 'mainnet'
+client = in3.Client(chain)
+address = client.ens_address(domain)
+owner = client.ens_owner(domain)
+_print()
- url: https://tincubeth.komputing.org/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578947320
+# Instantiate In3 Client for Kovan
+chain = 'kovan'
+client = in3.Client(chain)
+try:
+ address = client.ens_address(domain)
+ owner = client.ens_owner(domain)
+ _print()
+except in3.ClientException:
+ print('\nENS is not available on Kovan.')
+
+
+# Produces
+"""
+Ethereum Name Service
+Address for depraz.eth @ mainnet: 0x0b56ae81586d2728ceaf7c00a6020c5d63f02308
+Owner for depraz.eth @ mainnet: 0x6fa33809667a99a805b610c49ee2042863b1bb83
- url: https://h5l45fkzz7oc3gmb.onion/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578954071
+ENS is not available on Kovan.
"""
+
```
+### send_transaction
+
+source : [in3-c/python/examples/send_transaction.py](https://github.com/slockit/in3-c/blob/master/python/examples/send_transaction.py)
+
+
+
+```python
+"""
+Sends Ethereum transactions using Incubed.
+Incubed send Transaction does all necessary automation to make sending a transaction a breeze.
+Works with included `data` field for smart-contract calls.
+"""
+import json
+import in3
+import time
+
+
+# On Metamask, be sure to be connected to the correct chain, click on the `...` icon on the right corner of
+# your Account name, select `Account Details`. There, click `Export Private Key`, copy the value to use as secret.
+sender_secret = hex(0x9852782D2AD26C64161665586D23391ECED2D2ED7432A1D26FD326D28EA0171F)
+receiver = hex(0x6FA33809667A99A805b610C49EE2042863b1bb83)
+# 1000000000000000000 == 1 ETH
+value_in_wei = 1463926659
+chain = 'goerli'
+client = in3.Client(chain)
+# A transaction is only final if a certain number of blocks are mined on top of it.
+# This number varies with the chain's consensus algorithm. Time can be calculated over using:
+# wait_time = blocks_for_consensus * avg_block_time_in_secs
+confirmation_wait_time_in_seconds = 25
+etherscan_link_mask = 'https://{}{}etherscan.io/tx/{}'
+
+print('Ethereum Transaction using Incubed\n')
+try:
+ sender = client.eth.account.recover(sender_secret)
+ tx = in3.eth.NewTransaction(to=receiver, value=value_in_wei)
+ print('Sending {} Wei from {} to {}.\n'.format(tx.value, sender.address, tx.to))
+ tx_hash = client.eth.account.send_transaction(sender, tx)
+ print('Transaction accepted with hash {}.'.format(tx_hash))
+ add_dot_if_chain = '.' if chain else ''
+ print(etherscan_link_mask.format(chain, add_dot_if_chain, tx_hash))
+ print('\nWaiting {} seconds for confirmation.\n'.format(confirmation_wait_time_in_seconds))
+ time.sleep(confirmation_wait_time_in_seconds)
+ receipt: in3.eth.TransactionReceipt = client.eth.transaction_receipt(tx_hash)
+ print('Transaction was sent successfully!')
+ print(json.dumps(receipt.to_dict(), indent=4, sort_keys=True))
+ print('\nMined on block {} used {} GWei.'.format(receipt.blockNumber, receipt.gasUsed))
+except in3.PrivateKeyNotFoundException as e:
+ print(str(e))
+except in3.ClientException as e:
+ print('Client returned error: ', str(e))
+ print('Please try again.')
+
+# Response
+"""
+Ethereum Transaction using Incubed
+
+Sending 1463926659 Wei from 0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308 to 0x6fa33809667a99a805b610c49ee2042863b1bb83.
+
+Transaction accepted with hash 0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3.
+https://goerli.etherscan.io/tx/0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3
+
+Waiting 25 seconds for confirmation.
+
+Transaction was sent successfully!
+{
+ "From": "0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308",
+ "blockHash": "0x9693714c9d7dbd31f36c04fbd262532e68301701b1da1a4ee8fc04e0386d868b",
+ "blockNumber": 2615346,
+ "cumulativeGasUsed": 21000,
+ "gasUsed": 21000,
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": 1,
+ "to": "0x6FA33809667A99A805b610C49EE2042863b1bb83",
+ "transactionHash": "0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3",
+ "transactionIndex": 0
+}
+
+Mined on block 2615346 used 21000 GWei.
+"""
+
+```
+
+### smart_contract
+
+source : [in3-c/python/examples/smart_contract.py](https://github.com/slockit/in3-c/blob/master/python/examples/smart_contract.py)
+
+
+
+```python
+"""
+Manually calling ENS smart-contract
+![UML Sequence Diagram of how Ethereum Name Service ENS resolves a name.](https://lh5.googleusercontent.com/_OPPzaxTxKggx9HuxloeWtK8ggEfIIBKRCEA6BKMwZdzAfUpIY6cz7NK5CFmiuw7TwknbhFNVRCJsswHLqkxUEJ5KdRzpeNbyg8_H9d2RZdG28kgipT64JyPZUP--bAizozaDcxCq34)
+"""
+import in3
+
+
+client = in3.Client('goerli')
+domain_name = client.ens_namehash('depraz.eth')
+ens_registry_addr = '0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e'
+ens_resolver_abi = 'resolver(bytes32):address'
+
+# Find resolver contract for ens name
+resolver_tx = {
+ "to": ens_registry_addr,
+ "data": client.eth.contract.encode(ens_resolver_abi, domain_name)
+}
+tx = in3.eth.NewTransaction(**resolver_tx)
+encoded_resolver_addr = client.eth.contract.call(tx)
+resolver_address = client.eth.contract.decode(ens_resolver_abi, encoded_resolver_addr)
+
+# Resolve name
+ens_addr_abi = 'addr(bytes32):address'
+name_tx = {
+ "to": resolver_address,
+ "data": client.eth.contract.encode(ens_addr_abi, domain_name)
+}
+encoded_domain_address = client.eth.contract.call(in3.eth.NewTransaction(**name_tx))
+domain_address = client.eth.contract.decode(ens_addr_abi, encoded_domain_address)
+
+print('END domain:\n{}\nResolved by:\n{}\nTo address:\n{}'.format(domain_name, resolver_address, domain_address))
+
+# Produces
+"""
+END domain:
+0x4a17491df266270a8801cee362535e520a5d95896a719e4a7d869fb22a93162e
+Resolved by:
+0x4b1488b7a6b320d2d721406204abc3eeaa9ad329
+To address:
+0x0b56ae81586d2728ceaf7c00a6020c5d63f02308
+"""
+
+```
### Running the examples
@@ -187,8 +390,9 @@ To run an example, you need to install in3 first:
```sh
pip install in3
```
+This will install the library system-wide. Please consider using `virtualenv` or `pipenv` for a project-wide install.
-Copy one of the examples, or both and paste into a file, i.e. `example.py`:
+Then copy one of the examples and paste into a file, i.e. `example.py`:
`MacOS`
```sh
@@ -200,12 +404,15 @@ Execute the example with python:
python example.py
```
-## in3
+## Incubed Modules
### Client
```python
-Client(self, in3_config: ClientConfig = None)
+Client(self,
+chain: str = 'mainnet',
+in3_config: ClientConfig = None,
+transport=)
```
Incubed network client. Connect to the blockchain via a list of bootnodes, then gets the latest list of nodes in
@@ -217,9 +424,9 @@ Once with the latest list at hand, the client can request any other on-chain inf
- `in3_config` _ClientConfig or str_ - (optional) Configuration for the client. If not provided, default is loaded.
-#### node_list
+#### refresh_node_list
```python
-Client.node_list()
+Client.refresh_node_list()
```
Gets the list of Incubed nodes registered in the selected chain registry contract.
@@ -229,136 +436,124 @@ Gets the list of Incubed nodes registered in the selected chain registry contrac
- `node_list` _NodeList_ - List of registered in3 nodes and metadata.
-#### abi_encode
+#### ens_namehash
```python
-Client.abi_encode(fn_signature: str, *fn_args)
+Client.ens_namehash(domain_name: str)
```
-Smart-contract ABI encoder. Used to serialize a rpc to the EVM.
-Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
-Note: Parameters refers to the list of variables in a method declaration.
-Arguments are the actual values that are passed in when the method is invoked.
-When you invoke a method, the arguments used must match the declaration's parameters in type and order.
+Name format based on [EIP-137](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax)
**Arguments**:
-- `fn_signature` _str_ - Function name, with parameters. i.e. `getBalance(uint256):uint256`, can contain the return types but will be ignored.
-- `fn_args` _tuple_ - Function parameters, in the same order as in passed on to method_name.
+- `domain_name` - ENS supported domain. mydomain.ens, mydomain.xyz, etc
**Returns**:
-- `encoded_fn_call` _str_ - i.e. "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890"
+- `node` _str_ - Formatted string referred as `node` in ENS documentation
-#### abi_decode
+#### ens_address
```python
-Client.abi_decode(fn_return_types: str, encoded_values: str)
+Client.ens_address(domain_name: str, registry: str = None)
```
-Smart-contract ABI decoder. Used to parse rpc responses from the EVM.
-Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
+Resolves ENS domain name to what account that domain points to.
**Arguments**:
-- `fn_return_types` - Function return types. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`.
- In case of the latter, the function signature will be ignored and only the return types will be parsed.
-- `encoded_values` - Abi encoded values. Usually the string returned from a rpc to the EVM.
+- `domain_name` - ENS supported domain. mydomain.ens, mydomain.xyz, etc
+- `registry` - ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
**Returns**:
-- `decoded_return_values` _tuple_ - "0x1234567890123456789012345678901234567890", "0x05"
+- `address` _str_ - Ethereum address corresponding to what account that domain points to.
-#### call
+#### ens_owner
```python
-Client.call(transaction: RawTransaction, block_number: int)
+Client.ens_owner(domain_name: str, registry: str = None)
```
-Calls a smart-contract method that does not store the computation. Will be executed locally by Incubed's EVM.
-curl localhost:8545 -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "eth.accounts[0]", "to": "0x65da172d668fbaeb1f60e206204c2327400665fd", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}, "latest"], "id":1}'
-Check https://ethereum.stackexchange.com/questions/3514/how-to-call-a-contract-method-using-the-eth-call-json-rpc-api for more.
+Resolves ENS domain name to Ethereum address of domain owner.
**Arguments**:
- transaction (RawTransaction):
-- `block_number` _int or str_ - Desired block number integer or 'latest', 'earliest', 'pending'.
+- `domain_name` - ENS supported domain. mydomain.ens, mydomain.xyz, etc
+- `registry` - ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
**Returns**:
-- `method_returned_value` - A hexadecimal. For decoding use in3.abi_decode.
+- `owner_address` _str_ - Ethereum address corresponding to domain owner.
-### ClientConfig
+#### ens_resolver
```python
-ClientConfig(self,
-chainId: str = 'mainnet',
-key: str = None,
-replaceLatestBlock: int = 8,
-signatureCount: int = 3,
-finality: int = 70,
-minDeposit: int = 10000000000000000,
-proof: In3ProofLevel = ,
-autoUpdateList: bool = True,
-timeout: int = 5000,
-includeCode: bool = False,
-keepIn3: bool = False,
-maxAttempts: int = None,
-maxBlockCache: int = None,
-maxCodeCache: int = None,
-nodeLimit: int = None,
-requestCount: int = 1)
-```
-
-In3 Client Configuration class.
-Determines the behavior of client, which chain to connect to, verification policy, update cycle, minimum number of
-signatures collected on every request, and response timeout.
-Those are the settings that determine information security levels. Considering integrity is guaranteed by and
-confidentiality is not available on public blockchains, these settings will provide a balance between availability,
-and financial stake in case of repudiation. The "newer" the block is, or the closest to "latest", the higher are
-the chances it gets repudiated (a fork) by the chain, making lower the chances a node will sign on such information
-and thus reducing its availability. Up to a certain point, the older the block gets, the highest is its
-availability because of the close-to-zero repudiation risk. Blocks older than circa one year are stored in Archive
-Nodes, expensive computers, so, despite of the zero repudiation risk, there are not many nodes and they must search
-for the requested block in its database, lowering the availability as well. The verification policy enforces an
-extra step of security, that proves important in case you have only one response from an archive node
-and want to run a local integrity check, just to be on the safe side.
-
-**Arguments**:
-
-- `chainId` _str_ - (optional) - servers to filter for the given chain. The chain-id based on EIP-155. example: 0x1
-- `replaceLatestBlock` _int_ - (optional) - if specified, the blocknumber latest will be replaced by blockNumber- specified value example: 6
-- `signatureCount` _int_ - (optional) - number of signatures requested example: 2
-- `finality` _int_ - (optional) - the number in percent needed in order reach finality (% of signature of the validators) example: 50
-- `minDeposit` _int_ - - min stake of the server. Only nodes owning at least this amount will be chosen.
- proof :'none'|'standard'|'full' (optional) - if true the nodes should send a proof of the response
-- `autoUpdateList` _bool_ - (optional) - if true the nodelist will be automatically updated if the lastBlock is newer
-- `timeout` _int_ - specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. example: 100000
-- `key` _str_ - (optional) - the client key to sign requests example: 0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7
-- `includeCode` _bool_ - (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
-- `maxAttempts` _int_ - (optional) - max number of attempts in case a response is rejected example: 10
-- `keepIn3` _bool_ - (optional) - if true, the in3-section of thr response will be kept. Otherwise it will be removed after validating the data. This is useful for debugging or if the proof should be used afterwards.
-- `maxBlockCache` _int_ - (optional) - number of number of blocks cached in memory example: 100
-- `maxCodeCache` _int_ - (optional) - number of max bytes used to cache the code in memory example: 100000
-- `nodeLimit` _int_ - (optional) - the limit of nodes to store in the client. example: 150
-- `requestCount` _int_ - - Useful to be higher than 1 when using signatureCount <= 1. Then the client check for consensus in answers.
+Client.ens_resolver(domain_name: str, registry: str = None)
+```
+
+Resolves ENS domain name to Smart-contract address of the resolver registered for that domain.
+
+**Arguments**:
+
+- `domain_name` - ENS supported domain. mydomain.ens, mydomain.xyz, etc
+- `registry` - ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
+
+**Returns**:
+
+- `resolver_contract_address` _str_ - Smart-contract address of the resolver registered for that domain.
-### NodeList
+### ClientConfig
```python
-NodeList(self, nodes: [], contract: Account,
-registryId: str, lastBlockNumber: int, totalServers: int)
+ClientConfig(self,
+chain_finality_threshold: int = None,
+account_secret: str = None,
+latest_block_stall: int = None,
+node_signatures: int = None,
+node_signature_consensus: int = None,
+node_min_deposit: int = None,
+node_list_auto_update: bool = None,
+node_limit: int = None,
+request_timeout: int = None,
+request_retries: int = None,
+response_proof_level: str = None,
+response_includes_code: bool = None,
+response_keep_proof: bool = None,
+cached_blocks: int = None,
+cached_code_bytes: int = None,
+in3_registry: dict = None)
```
-List of incubed nodes and its metadata, in3 registry contract from which the list was taken,
-network/registry id, and last block number in the selected chain.
+Determines the behavior of the in3 client, which chain to connect to and how to manage information security policies.
+
+Considering integrity is guaranteed and confidentiality is not available on public blockchains, these settings will provide a balance between availability, and financial stake in case of repudiation.
+
+The newer the block is, higher are the chances it gets repudiated by a fork in the chain. In3 nodes will decide individually to sign on repudiable information, reducing the availability. If the application needs the very latest block, consider using a calculated value in `node_signature_consensus` and set `node_signatures` to zero. This setting is as secure as a light-client.
+
+The older the block gets, the highest is its availability because of the close-to-zero repudiation risk, but blocks older than circa one year are stored in Archive Nodes, expensive computers, so, despite of the low risk, there are not many nodes available with such information, and they must search for the requested block in its database, lowering the availability as well. If the application needs access to _old_ blocks, consider setting `request_timeout` and `request_retries` to accomodate the time the archive nodes take to fetch the inforamtion.
+
+The verification policy enforces an extra step of security, adding a financial stake in case of repudiation or false/broken proof. For high security application, consider setting a calculated value in `node_min_deposit` and request as much signatures as necessary in `node_signatures`. Setting `chain_finality_threshold` high will guarantee non-repudiability.
+
+**All args are Optional. Defaults connect to Ethereum main network with regular security levels.**
**Arguments**:
-- `nodes` _[In3Node]_ - list of incubed nodes
-- `contract` _Account_ - incubed registry contract from which the list was taken
-- `registryId` _str_ - uuid of this incubed network. one chain could contain more than one incubed networks.
-- `lastBlockNumber` _int_ - last block signed by the network
-- `totalServers` _int_ - Total servers number (for integrity?)
+- `chain_finality_threshold` _int_ - Behavior depends on the chain consensus algorithm: POA - percent of signers needed in order reach finality (% of the validators) i.e.: 60 %. POW - mined blocks on top of the requested, i.e. 8 blocks. Defaults are defined in enum.Chain.
+- `latest_block_stall` _int_ - Distance considered safe, consensus wise, from the very latest block. Higher values exponentially increases state finality, and therefore data security, as well guaranteeded responses from in3 nodes. example: 10 - will ask for the state from (latestBlock-10).
+- `account_secret` _str_ - Account SK to sign all in3 requests. (Experimental use `set_account_sk`) example: 0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7
+- `node_signatures` _int_ - Node signatures attesting the response to your request. Will send a separate request for each. example: 3 nodes will have to sign the response.
+- `node_signature_consensus` _int_ - Useful when signatureCount <= 1. The client will check for consensus in responses. example: 10 - will ask for 10 different nodes and compare results looking for a consensus in the responses.
+- `node_min_deposit` _int_ - Only nodes owning at least this amount will be chosen to sign responses to your requests. i.e. 1000000000000000000 Wei
+- `node_list_auto_update` _bool_ - If true the nodelist will be automatically updated. False may compromise data security.
+- `node_limit` _int_ - Limit nodes stored in the client. example: 150 nodes
+- `request_timeout` _int_ - Milliseconds before a request times out. example: 100000 ms
+- `request_retries` _int_ - Maximum times the client will retry to contact a certain node. example: 10 retries
+- `response_proof_level` _str_ - 'none'|'standard'|'full' Full gets the whole block Patricia-Merkle-Tree, Standard only verifies the specific tree branch concerning the request, None only verifies the root hashes, like a light-client does.
+- `response_includes_code` _bool_ - If true, every request with the address field will include the data, if existent, that is stored in that wallet/smart-contract. If false, only the code digest is included.
+- `response_keep_proof` _bool_ - If true, proof data will be kept in every rpc response. False will remove this data after using it to verify the responses. Useful for debugging and manually verifying the proofs.
+- `cached_blocks` _int_ - Maximum blocks kept in memory. example: 100 last requested blocks
+- `cached_code_bytes` _int_ - Maximum number of bytes used to cache EVM code in memory. example: 100000 bytes
+- `in3_registry` _dict_ - In3 Registry Smart Contract configuration data
### In3Node
@@ -382,62 +577,103 @@ indeed mined are in the correct chain fork.
- `weight` _int_ - Score based on qualitative metadata to base which nodes to ask signatures from.
-## in3.eth
+### NodeList
+```python
+NodeList(self, nodes: [], contract: Account,
+registryId: str, lastBlockNumber: int, totalServers: int)
+```
+List of incubed nodes and its metadata, in3 registry contract from which the list was taken,
+network/registry id, and last block number in the selected chain.
-### EthereumApi
+**Arguments**:
+
+- `nodes` _[In3Node]_ - list of incubed nodes
+- `contract` _Account_ - incubed registry contract from which the list was taken
+- `registryId` _str_ - uuid of this incubed network. one chain could contain more than one incubed networks.
+- `lastBlockNumber` _int_ - last block signed by the network
+- `totalServers` _int_ - Total servers number (for integrity?)
+
+
+
+
+
+### EthAccountApi
```python
-EthereumApi(self, runtime: In3Runtime, chain_id: str)
+EthAccountApi(self, runtime: In3Runtime, factory: EthObjectFactory)
```
-Module based on Ethereum's api and web3.js
+Manages accounts and smart-contracts
-#### keccak256
+#### create
```python
-EthereumApi.keccak256(message: str)
+EthAccountApi.create(qrng=False)
```
-Keccak-256 digest of the given data. Compatible with Ethereum but not with SHA3-256.
+Creates a new Ethereum account and saves it in the wallet.
**Arguments**:
-- `message` _str_ - Message to be hashed.
+- `qrng` _bool_ - True uses a Quantum Random Number Generator api for generating the private key.
**Returns**:
-- `digest` _str_ - The message digest.
+- `account` _Account_ - Newly created Ethereum account.
-#### gas_price
+#### recover
```python
-EthereumApi.gas_price()
+EthAccountApi.recover(secret: str)
```
-The current gas price in Wei (1 ETH equals 1000000000000000000 Wei ).
+Recovers an account from a secret.
+
+**Arguments**:
+
+- `secret` _str_ - Account private key in hexadecimal string
**Returns**:
-- `price` _int_ - minimum gas value for the transaction to be mined
+- `account` _Account_ - Recovered Ethereum account.
-#### block_number
+#### parse_mnemonics
```python
-EthereumApi.block_number()
+EthAccountApi.parse_mnemonics(mnemonics: str)
```
-Returns the number of the most recent block the in3 network can collect signatures to verify.
-Can be changed by Client.Config.replaceLatestBlock.
-If you need the very latest block, change Client.Config.signatureCount to zero.
+Recovers an account secret from mnemonics phrase
+
+**Arguments**:
+
+- `mnemonics` _str_ - BIP39 mnemonics phrase.
**Returns**:
- block_number (int) : Number of the most recent block
+- `secret` _str_ - Account secret. Use `recover_account` to create a new account with this secret.
+
+
+#### sign
+```python
+EthAccountApi.sign(private_key: str, message: str)
+```
+
+Use ECDSA to sign a message.
+
+**Arguments**:
+
+- `private_key` _str_ - Must be either an address(20 byte) or an raw private key (32 byte)"}}'
+- `message` _str_ - Data to be hashed and signed. Dont input hashed data unless you know what you are doing.
+
+**Returns**:
+
+- `signed_message` _str_ - ECDSA calculated r, s, and parity v, concatenated. v = 27 + (r % 2)
-#### get_balance
+#### balance
```python
-EthereumApi.get_balance(address: str, at_block: int = 'latest')
+EthAccountApi.balance(address: str, at_block: int = 'latest')
```
Returns the balance of the account of given address.
@@ -452,51 +688,64 @@ Returns the balance of the account of given address.
- `balance` _int_ - integer of the current balance in wei.
-#### get_storage_at
+#### send_transaction
```python
-EthereumApi.get_storage_at(
-address: str,
-position: int = 0,
-at_block: int = )
+EthAccountApi.send_transaction(sender: Account,
+transaction: NewTransaction)
```
-Stored value in designed position at a given address. Storage can be used to store a smart contract state, constructor or just any data.
-Each contract consists of a EVM bytecode handling the execution and a storage to save the state of the contract.
-The storage is essentially a key/value store. Use get_code to get the smart-contract code.
+Signs and sends the assigned transaction. Requires `account.secret` value set.
+Transactions change the state of an account, just the balance, or additionally, the storage and the code.
+Every transaction has a cost, gas, paid in Wei. The transaction gas is calculated over estimated gas times the
+gas cost, plus an additional miner fee, if the sender wants to be sure that the transaction will be mined in the
+latest block.
**Arguments**:
-- `address` _str_ - Ethereum account address
-- `position` _int_ - Position index, 0x0 up to 0x64
-- `at_block` _int or str_ - Block number
+- `sender` _Account_ - Sender Ethereum account. Senders generally pay the gas costs, so they must have enough balance to pay gas + amount sent, if any.
+- `transaction` _NewTransaction_ - All information needed to perform a transaction. Minimum is to and value. Client will add the other required fields, gas and chaindId.
**Returns**:
-- `storage_at` _str_ - Stored value in designed position. Use decode('hex') to see ascii format of the hex data.
+- `tx_hash` _hex_ - Transaction hash, used to get the receipt and check if the transaction was mined.
-#### get_code
+#### send_raw_transaction
```python
-EthereumApi.get_code(address: str,
-at_block: int = )
+EthAccountApi.send_raw_transaction(signed_transaction: str)
```
-Smart-Contract bytecode in hexadecimal. If the account is a simple wallet the function will return '0x'.
+Sends a signed and encoded transaction.
**Arguments**:
-- `address` _str_ - Ethereum account address
-- `at_block` _int or str_ - Block number
+- `signed_transaction` - Signed keccak hash of the serialized transaction
+ Client will add the other required fields, gas and chaindId.
**Returns**:
-- `bytecode` _str_ - Smart-Contract bytecode in hexadecimal.
+- `tx_hash` _hex_ - Transaction hash, used to get the receipt and check if the transaction was mined.
-#### get_transaction_count
+#### estimate_gas
```python
-EthereumApi.get_transaction_count(
-address: str, at_block: int = )
+EthAccountApi.estimate_gas(transaction: NewTransaction)
+```
+
+Gas estimation for transaction. Used to fill transaction.gas field. Check RawTransaction docs for more on gas.
+
+**Arguments**:
+
+- `transaction` - Unsent transaction to be estimated. Important that the fields data or/and value are filled in.
+
+**Returns**:
+
+- `gas` _int_ - Calculated gas in Wei.
+
+
+#### transaction_count
+```python
+EthAccountApi.transaction_count(address: str, at_block: int = 'latest')
```
Number of transactions mined from this address. Used to set transaction nonce.
@@ -513,161 +762,260 @@ It exists to mitigate replay attacks.
- `tx_count` _int_ - Number of transactions mined from this address.
-#### get_block_by_hash
+#### checksum_address
```python
-EthereumApi.get_block_by_hash(block_hash: str,
-get_full_block: bool = False)
+EthAccountApi.checksum_address(address: str, add_chain_id: bool = True)
```
-Blocks can be identified by root hash of the block merkle tree (this), or sequential number in which it was mined (get_block_by_number).
+Will convert an upper or lowercase Ethereum address to a checksum address, that uses case to encode values.
+See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md).
**Arguments**:
-- `block_hash` _str_ - Desired block hash
-- `get_full_block` _bool_ - If true, returns the full transaction objects, otherwise only its hashes.
+- `address` - Ethereum address string or object.
+- `add_chain_id` _bool_ - Will append the chain id of the address, for multi-chain support, canonical for Eth.
**Returns**:
-- `block` _Block_ - Desired block, if exists.
+- `checksum_address` - EIP-55 compliant, mixed-case address object.
-#### get_block_by_number
+
+
+
+### EthContractApi
```python
-EthereumApi.get_block_by_number(block_number: [],
-get_full_block: bool = False)
+EthContractApi(self, runtime: In3Runtime, factory: EthObjectFactory)
```
-Blocks can be identified by sequential number in which it was mined, or root hash of the block merkle tree (this) (get_block_by_hash).
+Manages smart-contract data and transactions
+
+
+#### call
+```python
+EthContractApi.call(transaction: NewTransaction,
+block_number: int = 'latest')
+```
+
+Calls a smart-contract method. Will be executed locally by Incubed's EVM or signed and sent over to save the state changes.
+Check https://ethereum.stackexchange.com/questions/3514/how-to-call-a-contract-method-using-the-eth-call-json-rpc-api for more.
**Arguments**:
+ transaction (NewTransaction):
- `block_number` _int or str_ - Desired block number integer or 'latest', 'earliest', 'pending'.
-- `get_full_block` _bool_ - If true, returns the full transaction objects, otherwise only its hashes.
**Returns**:
-- `block` _Block_ - Desired block, if exists.
+- `method_returned_value` - A hexadecimal. For decoding use in3.abi_decode.
-#### get_transaction_by_hash
+#### storage_at
```python
-EthereumApi.get_transaction_by_hash(tx_hash: str)
+EthContractApi.storage_at(address: str,
+position: int = 0,
+at_block: int = 'latest')
```
-Transactions can be identified by root hash of the transaction merkle tree (this) or by its position in the block transactions merkle tree.
-Every transaction hash is unique for the whole chain. Collision could in theory happen, chances are 67148E-63%.
+Stored value in designed position at a given address. Storage can be used to store a smart contract state, constructor or just any data.
+Each contract consists of a EVM bytecode handling the execution and a storage to save the state of the contract.
+The storage is essentially a key/value store. Use get_code to get the smart-contract code.
**Arguments**:
-- `tx_hash` - Transaction hash.
+- `address` _str_ - Ethereum account address
+- `position` _int_ - Position index, 0x0 up to 0x64
+- `at_block` _int or str_ - Block number
**Returns**:
-- `transaction` - Desired transaction, if exists.
+- `storage_at` _str_ - Stored value in designed position. Use decode('hex') to see ascii format of the hex data.
-### EthAccountApi
+#### code
```python
-EthAccountApi(self, runtime: In3Runtime, factory: EthObjectFactory)
+EthContractApi.code(address: str, at_block: int = 'latest')
```
-Manages wallets and smart-contracts
+Smart-Contract bytecode in hexadecimal. If the account is a simple wallet the function will return '0x'.
+
+**Arguments**:
+- `address` _str_ - Ethereum account address
+- `at_block` _int or str_ - Block number
-#### sign
+**Returns**:
+
+- `bytecode` _str_ - Smart-Contract bytecode in hexadecimal.
+
+
+#### encode
```python
-EthAccountApi.sign(address: str, data: str)
+EthContractApi.encode(fn_signature: str, *fn_args)
```
-Use ECDSA to sign a message.
+Smart-contract ABI encoder. Used to serialize a rpc to the EVM.
+Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
+Note: Parameters refers to the list of variables in a method declaration.
+Arguments are the actual values that are passed in when the method is invoked.
+When you invoke a method, the arguments used must match the declaration's parameters in type and order.
**Arguments**:
-- `address` _str_ - Ethereum address of the wallet that will sign the message.
-- `data` _str_ - Data to be signed, EITHER a hash string or a Transaction.
+- `fn_signature` _str_ - Function name, with parameters. i.e. `getBalance(uint256):uint256`, can contain the return types but will be ignored.
+- `fn_args` _tuple_ - Function parameters, in the same order as in passed on to method_name.
**Returns**:
-- `signed_message` _str_ - ECDSA calculated r, s, and parity v, concatenated. v = 27 + (r % 2)
+- `encoded_fn_call` _str_ - i.e. "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890"
-#### send_transaction
+#### decode
```python
-EthAccountApi.send_transaction(transaction: RawTransaction)
+EthContractApi.decode(fn_signature: str, encoded_value: str)
```
-Signs and sends the assigned transaction. Requires the 'key' value to be set in ClientConfig.
-Transactions change the state of an account, just the balance, or additionally, the storage and the code.
-Every transaction has a cost, gas, paid in Wei. The transaction gas is calculated over estimated gas times the
-gas cost, plus an additional miner fee, if the sender wants to be sure that the transaction will be mined in the
-latest block.
+Smart-contract ABI decoder. Used to parse rpc responses from the EVM.
+Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
**Arguments**:
-- `transaction` - All information needed to perform a transaction. Minimum is from, to and value.
- Client will add the other required fields, gas and chaindId.
+- `fn_signature` - Function signature. e.g. `(address,string,uint256)` or `getBalance(address):uint256`.
+ In case of the latter, the function signature will be ignored and only the return types will be parsed.
+- `encoded_value` - Abi encoded values. Usually the string returned from a rpc to the EVM.
**Returns**:
-- `tx_hash` - Transaction hash, used to get the receipt and check if the transaction was mined.
+- `decoded_return_values` _tuple_ - "0x1234567890123456789012345678901234567890", "0x05"
-#### get_transaction_receipt
+
+
+
+### EthereumApi
```python
-EthAccountApi.get_transaction_receipt(tx_hash: str)
+EthereumApi(self, runtime: In3Runtime)
```
-After a transaction is received the by the client, it returns the transaction hash. With it, it is possible to
-gather the receipt, once a miner has mined and it is part of an acknowledged block. Because how it is possible,
-in distributed systems, that data is asymmetric in different parts of the system, the transaction is only "final"
-once a certain number of blocks was mined after it, and still it can be possible that the transaction is discarded
-after some time. But, in general terms, it is accepted that after 6 to 8 blocks from latest, that it is very
-likely that the transaction will stay in the chain.
+Module based on Ethereum's api and web3.js
+
+
+#### keccak256
+```python
+EthereumApi.keccak256(message: str)
+```
+
+Keccak-256 digest of the given data. Compatible with Ethereum but not with SHA3-256.
**Arguments**:
-- `tx_hash` - Transaction hash.
+- `message` _str_ - Message to be hashed.
**Returns**:
- tx_receipt:
+- `digest` _str_ - The message digest.
-#### estimate_gas
+#### gas_price
```python
-EthAccountApi.estimate_gas(transaction: RawTransaction)
+EthereumApi.gas_price()
```
-Gas estimation for transaction. Used to fill transaction.gas field. Check RawTransaction docs for more on gas.
+The current gas price in Wei (1 ETH equals 1000000000000000000 Wei ).
+
+**Returns**:
+
+- `price` _int_ - minimum gas value for the transaction to be mined
+
+
+#### block_number
+```python
+EthereumApi.block_number()
+```
+
+Returns the number of the most recent block the in3 network can collect signatures to verify.
+Can be changed by Client.Config.replaceLatestBlock.
+If you need the very latest block, change Client.Config.signatureCount to zero.
+
+**Returns**:
+
+ block_number (int) : Number of the most recent block
+
+
+#### block_by_hash
+```python
+EthereumApi.block_by_hash(block_hash: str, get_full_block: bool = False)
+```
+
+Blocks can be identified by root hash of the block merkle tree (this), or sequential number in which it was mined (get_block_by_number).
**Arguments**:
-- `transaction` - Unsent transaction to be estimated. Important that the fields data or/and value are filled in.
+- `block_hash` _str_ - Desired block hash
+- `get_full_block` _bool_ - If true, returns the full transaction objects, otherwise only its hashes.
**Returns**:
-- `gas` _int_ - Calculated gas in Wei.
+- `block` _Block_ - Desired block, if exists.
-#### checksum_address
+#### block_by_number
```python
-EthAccountApi.checksum_address(address: str, add_chain_id: bool = True)
+EthereumApi.block_by_number(block_number: [],
+get_full_block: bool = False)
```
-Will convert an upper or lowercase Ethereum address to a checksum address, that uses case to encode values.
-See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md).
+Blocks can be identified by sequential number in which it was mined, or root hash of the block merkle tree (this) (get_block_by_hash).
**Arguments**:
-- `address` - Ethereum address string or object.
-- `add_chain_id` _bool_ - Will append the chain id of the address, for multi-chain support, canonical for Eth.
+- `block_number` _int or str_ - Desired block number integer or 'latest', 'earliest', 'pending'.
+- `get_full_block` _bool_ - If true, returns the full transaction objects, otherwise only its hashes.
**Returns**:
-- `checksum_address` - EIP-55 compliant, mixed-case address object.
+- `block` _Block_ - Desired block, if exists.
-### in3.eth.model
+#### transaction_by_hash
+```python
+EthereumApi.transaction_by_hash(tx_hash: str)
+```
+
+Transactions can be identified by root hash of the transaction merkle tree (this) or by its position in the block transactions merkle tree.
+Every transaction hash is unique for the whole chain. Collision could in theory happen, chances are 67148E-63%.
+
+**Arguments**:
+
+- `tx_hash` - Transaction hash.
+
+**Returns**:
+
+- `transaction` - Desired transaction, if exists.
+
+
+#### transaction_receipt
+```python
+EthereumApi.transaction_receipt(tx_hash: str)
+```
+
+After a transaction is received the by the client, it returns the transaction hash. With it, it is possible to
+gather the receipt, once a miner has mined and it is part of an acknowledged block. Because how it is possible,
+in distributed systems, that data is asymmetric in different parts of the system, the transaction is only "final"
+once a certain number of blocks was mined after it, and still it can be possible that the transaction is discarded
+after some time. But, in general terms, it is accepted that after 6 to 8 blocks from latest, that it is very
+likely that the transaction will stay in the chain.
+
+**Arguments**:
+
+- `tx_hash` - Transaction hash.
+
+**Returns**:
+
+- `tx_receipt` - The mined Transaction data including event logs.
+
+
+### Ethereum Objects
#### DataTransferObject
@@ -675,16 +1023,17 @@ See [EIP55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md).
DataTransferObject()
```
-Map marshalling objects transferred to and from a remote facade, in this case, libin3 rpc api.
+Maps marshalling objects transferred to, and from a remote facade, in this case, libin3 rpc api.
For more on design-patterns see [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
#### Transaction
```python
Transaction(self, From: str, to: str, gas: int, gasPrice: int, hash: str,
-data: str, nonce: int, gasLimit: int, blockNumber: int,
-transactionIndex: int, blockHash: str, value: int,
-signature: str)
+nonce: int, transactionIndex: int, blockHash: str,
+value: int, input: str, publicKey: str, standardV: int,
+raw: str, creates: str, chainId: int, r: int, s: int,
+v: int)
```
**Arguments**:
@@ -699,18 +1048,17 @@ signature: str)
- `nonce` _int_ - Number of transactions mined from this address. Nonce is a value that will make a transaction fail in case it is different from (transaction count + 1). It exists to mitigate replay attacks. This allows to overwrite your own pending transactions by sending a new one with the same nonce. Use in3.eth.account.get_transaction_count to get the latest value.
- `hash` _hex str_ - Keccak of the transaction bytes, not part of the transaction. Also known as receipt, because this field is filled after the transaction is sent, by eth_sendTransaction
- `blockHash` _hex str_ - Block hash that this transaction was mined in. null when its pending.
-- `blockNumber` _int_ - Block number that this transaction was mined in. null when its pending.
+- `blockHash` _int_ - Block number that this transaction was mined in. null when its pending.
- `transactionIndex` _int_ - Integer of the transactions index position in the block. null when its pending.
- `signature` _hex str_ - ECDSA of transaction.data, calculated r, s and v concatenated. V is parity set by v = 27 + (r % 2).
-#### RawTransaction
+#### NewTransaction
```python
-RawTransaction(self,
-From: str,
-to: str,
-gas: int,
-nonce: int,
+NewTransaction(self,
+From: str = None,
+to: str = None,
+nonce: int = None,
value: int = None,
data: str = None,
gasPrice: int = None,
@@ -725,7 +1073,6 @@ Unsent transaction. Use to send a new transaction.
- `From` _hex str_ - Address of the sender account.
- `to` _hex str_ - Address of the receiver account. Left undefined for a contract creation transaction.
-- `gas` _int_ - Gas for the transaction miners and execution in wei. Will get multiplied by `gasPrice`. Use in3.eth.account.estimate_gas to get a calculated value. Set too low and the transaction will run out of gas.
- `value` _int_ - (optional) Value transferred in wei. The endowment for a contract creation transaction.
- `data` _hex str_ - (optional) Either a ABI byte string containing the data of the function call on a contract, or in the case of a contract-creation transaction the initialisation code.
- `gasPrice` _int_ - (optional) Price of gas in wei, defaults to in3.eth.gasPrice. Also know as `tx fee price`. Set your gas price too low and your transaction may get stuck. Set too high on your own loss.
@@ -746,54 +1093,103 @@ An event will be stored in case it is within to and from blocks, or in the block
transaction to the designed address, and has a word listed on topics.
-#### Account
+#### Log
```python
-Account(self, address: str, chain_id: str, secret: str = None)
+Log(self, address: ,
+blockHash: , blockNumber: int,
+data: , logIndex: int, removed: bool,
+topics: [],
+transactionHash: , transactionIndex: int,
+transactionLogIndex: int, Type: str)
```
-Ethereum address of a wallet or smart-contract
-
+Transaction Log for events and data returned from smart-contract method calls.
-## in3.libin3
-
-### In3Runtime
+#### TransactionReceipt
```python
-In3Runtime(self, timeout: int)
+TransactionReceipt(self,
+blockHash: ,
+blockNumber: int,
+cumulativeGasUsed: int,
+From: str,
+gasUsed: int,
+logsBloom: ,
+status: int,
+transactionHash: ,
+transactionIndex: int,
+logs: [] = None,
+to: str = None,
+contractAddress: str = None)
```
-Instantiate libin3 and frees it when garbage collected.
+Receipt from a mined transaction.
**Arguments**:
-- `timeout` _int_ - Time for http request connection and content timeout in milliseconds
+ blockHash:
+ blockNumber:
+- `cumulativeGasUsed` - total amount of gas used by block
+ From:
+- `gasUsed` - amount of gas used by this specific transaction
+ logs:
+ logsBloom:
+- `status` - 1 if transaction succeeded, 0 otherwise.
+ transactionHash:
+ transactionIndex:
+- `to` - Account to which this transaction was sent. If the transaction was a contract creation this value is set to None.
+- `contractAddress` - Contract Account address created, f the transaction was a contract creation, or None otherwise.
-#### call
+#### Account
```python
-In3Runtime.call(fn_name: str, *args)
+Account(self,
+address: str,
+chain_id: int,
+secret: int = None,
+domain: str = None)
```
-Make a remote procedure call to a function in libin3
+An Ethereum account.
**Arguments**:
-- `fn_name` _str or Enum_ - Name of the function to be called
-- `*args` - Arguments matching the parameters order of this function
+- `address` - Account address. Derived from public key.
+- `chain_id` - ID of the chain the account is used in.
+- `secret` - Account private key. A 256 bit number.
+- `domain` - ENS Domain name. ie. niceguy.eth
+
+
+## Library Runtime
+
+Shared Library Runtime module
+
+Loads `libin3` according to host hardware architecture and OS.
+Maps symbols, methods and types from the library.
+Encapsulates low-level rpc calls into a comprehensive runtime.
-**Returns**:
-- `fn_return` _str_ - String of values returned by the function, if any.
+### In3Runtime
+```python
+In3Runtime(self, chain_id: int,
+transport: )
+```
+
+Instantiate libin3 and frees it when garbage collected.
+
+**Arguments**:
+
+- `chain_id` _int_ - Chain-id based on EIP-155. If None provided, will connect to the Ethereum network. i.e: 0x1 for mainNet
-### in3.libin3.lib_loader
+### Library Loader
-Load libin3 shared library for the current system, map function signatures, map and set transport functions.
+Load libin3 shared library for the current system, map function ABI, sets in3 network transport functions.
Example of RPC to In3-Core library, In3 Network and back.
```
+----------------+ +----------+ +------------+ +------------------+
-| | in3.client.eth.block_number() | | in3_client_exec_req | | In3 Network Request | |e
+| | in3.client.eth.block_number() | | in3_client_rpc | | In3 Network Request | |e
| python +------------------------------>+ python +-----------------------> libin3 +------------------------> python |
| application | | in3 | | in3-core | | http_transport |
| <-------------------------------+ <-----------------------+ <------------------------+ |
@@ -801,65 +1197,90 @@ Example of RPC to In3-Core library, In3 Network and back.
```
-#### In3Request
+#### libin3_new
```python
-In3Request()
+libin3_new(chain_id: int,
+transport: ,
+debug=False)
```
-Request sent by the libin3 to the In3 Network, transported over the _http_transport function
-Based on in3/client/.h in3_request_t struct
+Instantiate new In3 Client instance.
+
+**Arguments**:
+
+- `chain_id` _int_ - Chain id as integer
+- `transport` - Transport function for the in3 network requests
+- `debug` - Turn on debugger logging
-**Attributes**:
+**Returns**:
-- `payload` _str_ - the payload to send
-- `urls` _[str]_ - array of urls
-- `urls_len` _int_ - number of urls
-- `results` _str_ - the responses
-- `timeout` _int_ - the timeout 0= no timeout
-- `times` _int_ - measured times (in ms) which will be used for ajusting the weights
+- `instance` _int_ - Memory address of the client instance, return value from libin3_new
-#### libin3_new
+#### libin3_free
```python
-libin3_new(timeout: int)
+libin3_free(instance: int)
```
-RPC to free libin3 objects in memory.
+Free In3 Client objects from memory.
**Arguments**:
-- `timeout` _int_ - Time in milliseconds for http requests to fail due to timeout
-
-**Returns**:
-
-- `instance` _int_ - Memory address of the shared library instance, return value from libin3_new
+- `instance` _int_ - Memory address of the client instance, return value from libin3_new
-#### libin3_free
+#### libin3_exec
```python
-libin3_free(instance: int)
+libin3_exec(instance: int, rpc: bytes)
```
-RPC to free libin3 objects in memory.
+Make Remote Procedure Call mapped methods in the client.
**Arguments**:
-- `instance` _int_ - Memory address of the shared library instance, return value from libin3_new
+- `instance` _int_ - Memory address of the client instance, return value from libin3_new
+- `rpc` _bytes_ - Serialized function call, a json string.
+
+**Returns**:
+
+- `returned_value` _object_ - The returned function value(s)
#### libin3_call
```python
-libin3_call(instance: int, rpc: bytes)
+libin3_call(instance: int, fn_name: bytes, fn_args: bytes)
```
Make Remote Procedure Call to an arbitrary method of a libin3 instance
**Arguments**:
-- `instance` _int_ - Memory address of the shared library instance, return value from libin3_new
-- `rpc` _bytes_ - Serialized function call, a ethreum api json string.
+- `instance` _int_ - Memory address of the client instance, return value from libin3_new
+- `fn_name` _bytes_ - Name of function that will be called in the client rpc.
+- `fn_args` - (bytes) Serialized list of arguments, matching the parameters order of this function. i.e. ['0x123']
**Returns**:
-- `returned_value` _object_ - The returned function value(s)
+- `result` _int_ - Function execution status.
+
+#### libin3_set_pk
+```python
+libin3_set_pk(instance: int, private_key: bytes)
+```
+
+Register the signer module in the In3 Client instance, with selected private key loaded in memory.
+
+**Arguments**:
+
+- `instance` _int_ - Memory address of the client instance, return value from libin3_new
+- `private_key` - 256 bit number.
+
+
+#### init
+```python
+init()
+```
+
+Loads library depending on host system.
+
diff --git a/python/docs/pydocmd.yml b/python/docs/pydocmd.yml
index 478b56a77..f88ee8dc6 100644
--- a/python/docs/pydocmd.yml
+++ b/python/docs/pydocmd.yml
@@ -9,29 +9,36 @@ site_name: "Incubed Client for Python"
generate:
- libin3.md:
- in3.libin3:
- - in3.libin3.runtime.In3Runtime+
+ - in3.libin3.runtime.In3Runtime
- in3.libin3.lib_loader+
- eth.md:
- in3.eth:
- in3.eth.api.EthereumApi+
- - in3.eth.account.EthAccountApi+
- in3.eth.model+
+ - account.md:
+ - in3.eth.account:
+ - in3.eth.account.EthAccountApi+
+ - contract.md:
+ - in3.eth.contract:
+ - in3.eth.contract.EthContractApi+
- in3.md:
- in3:
- in3.client.Client+
- in3.model.ClientConfig
- - in3.model.NodeList
- in3.model.In3Node
+ - in3.model.NodeList
# MkDocs pages configuration. The `<<` operator is sugar added by pydocmd
# that allows you to use an external Markdown file (eg. your project's README)
# in the documentation. The path must be relative to current working directory.
pages:
- Home: index.md << ../README.md
- - Examples: examples.md << 2_examples.md
+ - Examples: examples.md << compiled_examples.md
- Internal Components:
- Client: in3.md
- Ethereum API: eth.md
+ - Ethereum Account API: account.md
+ - Ethereum Smart-Contract API: contract.md
- Libin3 Runtime: libin3.md
# These options all show off their default values. You don't have to add
diff --git a/python/examples/README.md b/python/examples/README.md
new file mode 100644
index 000000000..609fb74cb
--- /dev/null
+++ b/python/examples/README.md
@@ -0,0 +1,32 @@
+# Examples
+
+
+- [connect_to_ethereum](./connect_to_ethereum.py)
+
+- [incubed_network](./incubed_network.py)
+
+- [resolve_eth_names](./resolve_eth_names.py)
+
+- [send_transaction](./send_transaction.py)
+
+- [smart_contract](./smart_contract.py)
+
+### Running the examples
+
+To run an example, you need to install in3 first:
+```sh
+pip install in3
+```
+This will install the library system-wide. Please consider using `virtualenv` or `pipenv` for a project-wide install.
+
+Then copy one of the examples and paste into a file, i.e. `example.py`:
+
+`MacOS`
+```sh
+pbpaste > example.py
+```
+
+Execute the example with python:
+```
+python example.py
+```
diff --git a/python/examples/block_number.py b/python/examples/connect_to_ethereum.py
similarity index 90%
rename from python/examples/block_number.py
rename to python/examples/connect_to_ethereum.py
index 25f12d6cc..b6f77094b 100644
--- a/python/examples/block_number.py
+++ b/python/examples/connect_to_ethereum.py
@@ -1,3 +1,6 @@
+"""
+Connects to Ethereum and fetches attested information from each chain.
+"""
import in3
@@ -19,7 +22,7 @@
gas_price = client.eth.gas_price()
print('Latest BN: {}\nGas Price: {} Wei'.format(latest_block, gas_price))
-# Results Example
+# Produces
"""
Ethereum Main Network
Latest BN: 9801135
@@ -32,4 +35,4 @@
Ethereum Goerli Test Network
Latest BN: 2460853
Gas Price: 4610612736 Wei
-"""
\ No newline at end of file
+"""
diff --git a/python/examples/in3_config.py b/python/examples/in3_config.py
deleted file mode 100644
index 8e79e7d91..000000000
--- a/python/examples/in3_config.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import in3
-
-if __name__ == '__main__':
-
- print('\nEthereum Goerli Test Network')
- goerli_cfg = in3.ClientConfig(chainId=str(in3.Chain.GOERLI), signatureCount=3, timeout=10000)
- client = in3.Client(goerli_cfg)
- node_list = client.node_list()
- print('\nIncubed Registry:')
- print('\ttotal servers:', node_list.totalServers)
- print('\tlast updated in block:', node_list.lastBlockNumber)
- print('\tregistry ID:', node_list.registryId)
- print('\tcontract address:', node_list.contract)
- print('\nNodes Registered:\n')
- for node in node_list.nodes:
- print('\turl:', node.url)
- print('\tdeposit:', node.deposit)
- print('\tweight:', node.weight)
- print('\tregistered in block:', node.registerTime)
- print('\n')
-
-# Results Example
-"""
-Ethereum Goerli Test Network
-
-Incubed Registry:
- total servers: 7
- last updated in block: 2320627
- registry ID: 0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea
- contract address: 0x5f51e413581dd76759e9eed51e63d14c8d1379c8
-
-Nodes Registered:
-
- url: https://in3-v2.slock.it/goerli/nd-1
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227711
-
-
- url: https://in3-v2.slock.it/goerli/nd-2
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227741
-
-
- url: https://in3-v2.slock.it/goerli/nd-3
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227801
-
-
- url: https://in3-v2.slock.it/goerli/nd-4
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227831
-
-
- url: https://in3-v2.slock.it/goerli/nd-5
- deposit: 10000000000000000
- weight: 2000
- registered in block: 1576227876
-
-
- url: https://tincubeth.komputing.org/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578947320
-
-
- url: https://h5l45fkzz7oc3gmb.onion/
- deposit: 10000000000000000
- weight: 1
- registered in block: 1578954071
-"""
\ No newline at end of file
diff --git a/python/examples/incubed_network.py b/python/examples/incubed_network.py
new file mode 100644
index 000000000..3301ada81
--- /dev/null
+++ b/python/examples/incubed_network.py
@@ -0,0 +1,74 @@
+"""
+Shows Incubed Network Nodes Stats
+"""
+import in3
+
+print('\nEthereum Goerli Test Network')
+client = in3.Client('goerli')
+node_list = client.refresh_node_list()
+print('\nIncubed Registry:')
+print('\ttotal servers:', node_list.totalServers)
+print('\tlast updated in block:', node_list.lastBlockNumber)
+print('\tregistry ID:', node_list.registryId)
+print('\tcontract address:', node_list.contract)
+print('\nNodes Registered:\n')
+for node in node_list.nodes:
+ print('\turl:', node.url)
+ print('\tdeposit:', node.deposit)
+ print('\tweight:', node.weight)
+ print('\tregistered in block:', node.registerTime)
+ print('\n')
+
+# Produces
+"""
+Ethereum Goerli Test Network
+
+Incubed Registry:
+ total servers: 7
+ last updated in block: 2320627
+ registry ID: 0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea
+ contract address: 0x5f51e413581dd76759e9eed51e63d14c8d1379c8
+
+Nodes Registered:
+
+ url: https://in3-v2.slock.it/goerli/nd-1
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227711
+
+
+ url: https://in3-v2.slock.it/goerli/nd-2
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227741
+
+
+ url: https://in3-v2.slock.it/goerli/nd-3
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227801
+
+
+ url: https://in3-v2.slock.it/goerli/nd-4
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227831
+
+
+ url: https://in3-v2.slock.it/goerli/nd-5
+ deposit: 10000000000000000
+ weight: 2000
+ registered in block: 1576227876
+
+
+ url: https://tincubeth.komputing.org/
+ deposit: 10000000000000000
+ weight: 1
+ registered in block: 1578947320
+
+
+ url: https://h5l45fkzz7oc3gmb.onion/
+ deposit: 10000000000000000
+ weight: 1
+ registered in block: 1578954071
+"""
diff --git a/python/examples/resolve_eth_names.py b/python/examples/resolve_eth_names.py
new file mode 100644
index 000000000..d567859d0
--- /dev/null
+++ b/python/examples/resolve_eth_names.py
@@ -0,0 +1,49 @@
+"""
+Resolves ENS domains to Ethereum addresses
+ENS is a smart-contract system that registers and resolves `.eth` domains.
+"""
+import in3
+
+
+def _print():
+ print('\nAddress for {} @ {}: {}'.format(domain, chain, address))
+ print('Owner for {} @ {}: {}'.format(domain, chain, owner))
+
+
+# Find ENS for the desired chain or the address of your own ENS resolver. https://docs.ens.domains/ens-deployments
+domain = 'depraz.eth'
+
+print('\nEthereum Name Service')
+
+# Instantiate In3 Client for Goerli
+chain = 'goerli'
+client = in3.Client(chain)
+address = client.ens_address(domain)
+
+# Instantiate In3 Client for Mainnet
+chain = 'mainnet'
+client = in3.Client(chain)
+address = client.ens_address(domain)
+owner = client.ens_owner(domain)
+_print()
+
+# Instantiate In3 Client for Kovan
+chain = 'kovan'
+client = in3.Client(chain)
+try:
+ address = client.ens_address(domain)
+ owner = client.ens_owner(domain)
+ _print()
+except in3.ClientException:
+ print('\nENS is not available on Kovan.')
+
+
+# Produces
+"""
+Ethereum Name Service
+
+Address for depraz.eth @ mainnet: 0x0b56ae81586d2728ceaf7c00a6020c5d63f02308
+Owner for depraz.eth @ mainnet: 0x6fa33809667a99a805b610c49ee2042863b1bb83
+
+ENS is not available on Kovan.
+"""
diff --git a/python/examples/send_transaction.py b/python/examples/send_transaction.py
new file mode 100644
index 000000000..f7abd8eef
--- /dev/null
+++ b/python/examples/send_transaction.py
@@ -0,0 +1,72 @@
+"""
+Sends Ethereum transactions using Incubed.
+Incubed send Transaction does all necessary automation to make sending a transaction a breeze.
+Works with included `data` field for smart-contract calls.
+"""
+import json
+import in3
+import time
+
+
+# On Metamask, be sure to be connected to the correct chain, click on the `...` icon on the right corner of
+# your Account name, select `Account Details`. There, click `Export Private Key`, copy the value to use as secret.
+sender_secret = hex(0x9852782D2AD26C64161665586D23391ECED2D2ED7432A1D26FD326D28EA0171F)
+receiver = hex(0x6FA33809667A99A805b610C49EE2042863b1bb83)
+# 1000000000000000000 == 1 ETH
+value_in_wei = 1463926659
+chain = 'goerli'
+client = in3.Client(chain)
+# A transaction is only final if a certain number of blocks are mined on top of it.
+# This number varies with the chain's consensus algorithm. Time can be calculated over using:
+# wait_time = blocks_for_consensus * avg_block_time_in_secs
+confirmation_wait_time_in_seconds = 25
+etherscan_link_mask = 'https://{}{}etherscan.io/tx/{}'
+
+print('Ethereum Transaction using Incubed\n')
+try:
+ sender = client.eth.account.recover(sender_secret)
+ tx = in3.eth.NewTransaction(to=receiver, value=value_in_wei)
+ print('Sending {} Wei from {} to {}.\n'.format(tx.value, sender.address, tx.to))
+ tx_hash = client.eth.account.send_transaction(sender, tx)
+ print('Transaction accepted with hash {}.'.format(tx_hash))
+ add_dot_if_chain = '.' if chain else ''
+ print(etherscan_link_mask.format(chain, add_dot_if_chain, tx_hash))
+ print('\nWaiting {} seconds for confirmation.\n'.format(confirmation_wait_time_in_seconds))
+ time.sleep(confirmation_wait_time_in_seconds)
+ receipt: in3.eth.TransactionReceipt = client.eth.transaction_receipt(tx_hash)
+ print('Transaction was sent successfully!')
+ print(json.dumps(receipt.to_dict(), indent=4, sort_keys=True))
+ print('\nMined on block {} used {} GWei.'.format(receipt.blockNumber, receipt.gasUsed))
+except in3.PrivateKeyNotFoundException as e:
+ print(str(e))
+except in3.ClientException as e:
+ print('Client returned error: ', str(e))
+ print('Please try again.')
+
+# Response
+"""
+Ethereum Transaction using Incubed
+
+Sending 1463926659 Wei from 0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308 to 0x6fa33809667a99a805b610c49ee2042863b1bb83.
+
+Transaction accepted with hash 0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3.
+https://goerli.etherscan.io/tx/0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3
+
+Waiting 25 seconds for confirmation.
+
+Transaction was sent successfully!
+{
+ "From": "0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308",
+ "blockHash": "0x9693714c9d7dbd31f36c04fbd262532e68301701b1da1a4ee8fc04e0386d868b",
+ "blockNumber": 2615346,
+ "cumulativeGasUsed": 21000,
+ "gasUsed": 21000,
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": 1,
+ "to": "0x6FA33809667A99A805b610C49EE2042863b1bb83",
+ "transactionHash": "0xbeebda39e31e42d2a26476830fdcdc2d21e9df090af203e7601d76a43074d8d3",
+ "transactionIndex": 0
+}
+
+Mined on block 2615346 used 21000 GWei.
+"""
diff --git a/python/examples/smart_contract.py b/python/examples/smart_contract.py
new file mode 100644
index 000000000..e4f0bea5b
--- /dev/null
+++ b/python/examples/smart_contract.py
@@ -0,0 +1,41 @@
+"""
+Manually calling ENS smart-contract
+![UML Sequence Diagram of how Ethereum Name Service ENS resolves a name.](https://lh5.googleusercontent.com/_OPPzaxTxKggx9HuxloeWtK8ggEfIIBKRCEA6BKMwZdzAfUpIY6cz7NK5CFmiuw7TwknbhFNVRCJsswHLqkxUEJ5KdRzpeNbyg8_H9d2RZdG28kgipT64JyPZUP--bAizozaDcxCq34)
+"""
+import in3
+
+
+client = in3.Client('goerli')
+domain_name = client.ens_namehash('depraz.eth')
+ens_registry_addr = '0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e'
+ens_resolver_abi = 'resolver(bytes32):address'
+
+# Find resolver contract for ens name
+resolver_tx = {
+ "to": ens_registry_addr,
+ "data": client.eth.contract.encode(ens_resolver_abi, domain_name)
+}
+tx = in3.eth.NewTransaction(**resolver_tx)
+encoded_resolver_addr = client.eth.contract.call(tx)
+resolver_address = client.eth.contract.decode(ens_resolver_abi, encoded_resolver_addr)
+
+# Resolve name
+ens_addr_abi = 'addr(bytes32):address'
+name_tx = {
+ "to": resolver_address,
+ "data": client.eth.contract.encode(ens_addr_abi, domain_name)
+}
+encoded_domain_address = client.eth.contract.call(in3.eth.NewTransaction(**name_tx))
+domain_address = client.eth.contract.decode(ens_addr_abi, encoded_domain_address)
+
+print('END domain:\n{}\nResolved by:\n{}\nTo address:\n{}'.format(domain_name, resolver_address, domain_address))
+
+# Produces
+"""
+END domain:
+0x4a17491df266270a8801cee362535e520a5d95896a719e4a7d869fb22a93162e
+Resolved by:
+0x4b1488b7a6b320d2d721406204abc3eeaa9ad329
+To address:
+0x0b56ae81586d2728ceaf7c00a6020c5d63f02308
+"""
diff --git a/python/generate_docs.sh b/python/generate_docs.sh
index 169618743..0f5221ff3 100755
--- a/python/generate_docs.sh
+++ b/python/generate_docs.sh
@@ -1,9 +1,32 @@
#!/bin/bash
+source ../scripts/update_examples.sh
+cd ../python/docs || exit
-cd docs
pydocmd build
printf "# API Reference Python\n\n" > documentation.md
-cd _build/pydocmd
+
+cd _build/pydocmd || exit
cat index.md examples.md >> ../../documentation.md
-cat in3.md eth.md libin3.md | sed 's/# /## /' >> ../../documentation.md
-cd ..
\ No newline at end of file
+
+# shellcheck disable=SC2129
+sed 's/# /## /' in3.md |
+sed 's/^## in3$/## Incubed Modules/g' |
+sed 's/^### in3$//g' >> ../../documentation.md
+
+sed 's/# /## /' account.md |
+sed 's/^## in3.eth.account$//g' >> ../../documentation.md
+
+sed 's/# /## /' contract.md |
+sed 's/^## in3.eth.contract$//g' >> ../../documentation.md
+
+sed 's/# /## /' eth.md |
+sed 's/^## in3.eth$//g' |
+sed 's/^## in3.eth.model$//g' |
+sed 's/^### in3.eth.model$/### Ethereum Objects/g' >> ../../documentation.md
+
+sed 's/# /## /' libin3.md |
+sed 's/^## in3.libin3$/## Library Runtime/g' |
+sed 's/^### in3.libin3.lib_loader$/### Library Loader/g' >> ../../documentation.md
+
+cd ../..
+rm compiled_examples.md
\ No newline at end of file
diff --git a/python/in3/__init__.py b/python/in3/__init__.py
index ef952a15a..55207848c 100644
--- a/python/in3/__init__.py
+++ b/python/in3/__init__.py
@@ -1,12 +1,11 @@
-from in3.exception import IN3BaseException, EthAddressFormatException, HashFormatException, \
- NumberFormatException, PrivateKeyNotFoundException, ClientException
-from in3.model import ClientConfig
-from in3.libin3.enum import Chain
+import in3.eth.model as eth
from in3.client import Client
+from in3.exception import EthAddressFormatException, HashFormatException, PrivateKeyNotFoundException, ClientException
+from in3.model import ClientConfig, NodeList
__name__ = 'in3'
__author__ = 'Slock.it '
__repository__ = 'github.com/slockit/in3-c'
-__status__ = "pre-alpha"
+__status__ = "beta"
__version__ = "2.1"
-__date__ = "March 2020"
+__date__ = "May 2020"
diff --git a/python/in3/client.py b/python/in3/client.py
index 0f9451077..b4ea1649a 100644
--- a/python/in3/client.py
+++ b/python/in3/client.py
@@ -1,9 +1,9 @@
+from in3.eth.api import EthereumApi
from in3.eth.factory import EthObjectFactory
-from in3.eth.model import RawTransaction
+from in3.libin3.enum import In3Methods
from in3.libin3.runtime import In3Runtime
-from in3.libin3.enum import Chain, In3Methods
-from in3.eth.api import EthereumApi
-from in3.model import In3Node, NodeList, ClientConfig
+from in3.model import In3Node, NodeList, ClientConfig, ChainConfig, chain_configs
+from in3.transport import http_transport
class Client:
@@ -15,81 +15,93 @@ class Client:
in3_config (ClientConfig or str): (optional) Configuration for the client. If not provided, default is loaded.
"""
- def __init__(self, in3_config: ClientConfig or str = None):
- super().__init__()
- if isinstance(in3_config, ClientConfig):
- self.config = in3_config
- elif isinstance(in3_config, str):
- chain = next((item for item in Chain if item.value['alias'] == in3_config), False)
- if not chain:
- raise ValueError('Chain name not supported. Try mainnet, goerli or kovan')
- self.config = ClientConfig(chainId=str(chain))
- else:
- self.config = ClientConfig()
- self._runtime = In3Runtime(self.config.timeout)
- self._configure(in3_config=self.config)
- self.eth = EthereumApi(runtime=self._runtime, chain_id=self.config.chainId)
- self._factory = In3ObjectFactory(self.eth.account.checksum_address, self.config.chainId)
-
- def _configure(self, in3_config: ClientConfig):
- return self._runtime.call(In3Methods.CONFIG, in3_config.to_dict())
-
- def node_list(self) -> NodeList:
+ def __init__(self, chain: str or ChainConfig = 'mainnet',
+ in3_config: ClientConfig = None, transport=http_transport):
+
+ config = in3_config
+ if isinstance(chain, ChainConfig):
+ config = chain.client_config
+ elif not isinstance(chain, str) or chain not in ['mainnet', 'kovan', 'goerli']:
+ raise ValueError('Chain name not supported. Try mainnet, kovan, goerli.')
+
+ self._runtime = In3Runtime(chain_configs[chain].chain_id, transport)
+ if config:
+ # TODO: Chain_configs
+ self._configure(config)
+ # TODO: getConfig
+ self.eth = EthereumApi(self._runtime)
+ self._factory = In3ObjectFactory(self._runtime)
+
+ def _configure(self, in3_config: ClientConfig) -> bool:
+ """
+ Send RPC to change client configuration. Don't use outside the constructor, might cause instability.
+ """
+ fn_args = str([in3_config.serialize()]).replace('\'', '')
+ return self._runtime.call(In3Methods.CONFIGURE, fn_args, formatted=True)
+
+ def refresh_node_list(self) -> NodeList:
"""
Gets the list of Incubed nodes registered in the selected chain registry contract.
Returns:
node_list (NodeList): List of registered in3 nodes and metadata.
"""
- node_list_dict = self._runtime.call(In3Methods.IN3_NODE_LIST)
+ node_list_dict = self._runtime.call(In3Methods.NODE_LIST)
return self._factory.get_node_list(node_list_dict)
- def abi_encode(self, fn_signature: str, *fn_args) -> str:
+ def config(self) -> dict:
+ # TODO: Marshalling
+ return self._runtime.call(In3Methods.GET_CONFIG)
+
+ def ens_namehash(self, domain_name: str) -> str:
"""
- Smart-contract ABI encoder. Used to serialize a rpc to the EVM.
- Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
- Note: Parameters refers to the list of variables in a method declaration.
- Arguments are the actual values that are passed in when the method is invoked.
- When you invoke a method, the arguments used must match the declaration's parameters in type and order.
+ Name format based on [EIP-137](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#name-syntax)
Args:
- fn_signature (str): Function name, with parameters. i.e. `getBalance(uint256):uint256`, can contain the return types but will be ignored.
- fn_args (tuple): Function parameters, in the same order as in passed on to method_name.
+ domain_name: ENS supported domain. mydomain.ens, mydomain.xyz, etc
Returns:
- encoded_fn_call (str): i.e. "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890"
+ node (str): Formatted string referred as `node` in ENS documentation
"""
- # TODO: Smart-Contract Api
- return self._runtime.call(In3Methods.ABI_ENCODE, fn_signature, fn_args)
+ return self._runtime.call(In3Methods.ENSRESOLVE, domain_name, 'hash')
- def abi_decode(self, fn_return_types: str, encoded_values: str) -> tuple:
+ def ens_address(self, domain_name: str, registry: str = None) -> str:
"""
- Smart-contract ABI decoder. Used to parse rpc responses from the EVM.
- Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
+ Resolves ENS domain name to what account that domain points to.
Args:
- fn_return_types: Function return types. e.g. `uint256`, `(address,string,uint256)` or `getBalance(address):uint256`.
- In case of the latter, the function signature will be ignored and only the return types will be parsed.
- encoded_values: Abi encoded values. Usually the string returned from a rpc to the EVM.
+ domain_name: ENS supported domain. mydomain.ens, mydomain.xyz, etc
+ registry: ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
Returns:
- decoded_return_values (tuple): "0x1234567890123456789012345678901234567890", "0x05"
+ address (str): Ethereum address corresponding to what account that domain points to.
"""
- # TODO: Smart-Contract Api
- return self._runtime.call(In3Methods.ABI_DECODE, fn_return_types, encoded_values)
+ # TODO: Add handlers to Account
+ # TODO: Add serialization in account factory
+ if registry:
+ registry = self._factory.get_address(registry)
+ return self._runtime.call(In3Methods.ENSRESOLVE, domain_name, 'addr', registry)
- def call(self, transaction: RawTransaction, block_number: int or str) -> int or str:
+ def ens_owner(self, domain_name: str, registry: str = None) -> str:
"""
- Calls a smart-contract method that does not store the computation. Will be executed locally by Incubed's EVM.
- curl localhost:8545 -X POST --data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "eth.accounts[0]", "to": "0x65da172d668fbaeb1f60e206204c2327400665fd", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}, "latest"], "id":1}'
- Check https://ethereum.stackexchange.com/questions/3514/how-to-call-a-contract-method-using-the-eth-call-json-rpc-api for more.
+ Resolves ENS domain name to Ethereum address of domain owner.
Args:
- transaction (RawTransaction):
- block_number (int or str): Desired block number integer or 'latest', 'earliest', 'pending'.
+ domain_name: ENS supported domain. mydomain.ens, mydomain.xyz, etc
+ registry: ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
Returns:
- method_returned_value: A hexadecimal. For decoding use in3.abi_decode.
+ owner_address (str): Ethereum address corresponding to domain owner.
"""
- # different than eth_call
- # eth_call_fn(c, contract, BLKNUM_LATEST(), "servers(uint256):(string,address,uint,uint,uint,address)", to_uint256(i));
- return self._runtime.call(In3Methods.CALL, transaction, block_number)
+ if registry:
+ registry = self._factory.get_address(registry)
+ return self._runtime.call(In3Methods.ENSRESOLVE, domain_name, 'owner', registry)
- # TODO add eth_set_pk_signer
- # TODO add sign_tx
+ def ens_resolver(self, domain_name: str, registry: str = None) -> str:
+ """
+ Resolves ENS domain name to Smart-contract address of the resolver registered for that domain.
+ Args:
+ domain_name: ENS supported domain. mydomain.ens, mydomain.xyz, etc
+ registry: ENS registry contract address. i.e. 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
+ Returns:
+ resolver_contract_address (str): Smart-contract address of the resolver registered for that domain.
+ """
+ if registry:
+ registry = self._factory.get_address(registry)
+ return self._runtime.call(In3Methods.ENSRESOLVE, domain_name, 'resolver', registry)
class In3ObjectFactory(EthObjectFactory):
@@ -99,7 +111,7 @@ class In3ObjectFactory(EthObjectFactory):
def get_node_list(self, serialized: dict) -> NodeList:
mapping = {
"nodes": list,
- "contract": self.get_address,
+ "contract": self.get_account,
"registryId": str,
"lastBlockNumber": int,
"totalServers": int,
@@ -112,7 +124,7 @@ def get_node_list(self, serialized: dict) -> NodeList:
def get_in3node(self, serialized: dict) -> In3Node:
mapping = {
"url": str,
- "address": self.get_address,
+ "address": self.get_account,
"index": int,
"deposit": self.get_integer,
"props": str,
diff --git a/python/in3/eth/__init__.py b/python/in3/eth/__init__.py
index e69de29bb..c93e3a9fc 100644
--- a/python/in3/eth/__init__.py
+++ b/python/in3/eth/__init__.py
@@ -0,0 +1,3 @@
+"""
+Ethereum API module
+"""
diff --git a/python/in3/eth/account.py b/python/in3/eth/account.py
index 798baea81..25460faf3 100644
--- a/python/in3/eth/account.py
+++ b/python/in3/eth/account.py
@@ -1,80 +1,127 @@
-from in3.exception import ClientException
+import random
+
from in3.eth.factory import EthObjectFactory
+from in3.eth.model import NewTransaction, TransactionReceipt, Account
+from in3.exception import PrivateKeyNotFoundException
+from in3.libin3.enum import EthMethods, BlockAt, In3Methods
from in3.libin3.runtime import In3Runtime
-from in3.eth.model import RawTransaction
-from in3.libin3.enum import EthMethods
class EthAccountApi:
"""
- Manages wallets and smart-contracts
+ Manages accounts and smart-contracts
"""
def __init__(self, runtime: In3Runtime, factory: EthObjectFactory):
self._runtime = runtime
self._factory = factory
- def sign(self, address: str, data: str or RawTransaction) -> str:
+ def _create_account(self, secret: str) -> Account:
+ if not secret.startswith('0x') or not len(secret) == 66:
+ TypeError('Secret must be a 256 bit hexadecimal.')
+ address = self._runtime.call(In3Methods.PK_2_ADDRESS, secret)
+ account = self._factory.get_account(address, int(secret, 16))
+ return account
+
+ def create(self, qrng=False) -> Account:
+ """
+ Creates a new Ethereum account and saves it in the wallet.
+ Args:
+ qrng (bool): True uses a Quantum Random Number Generator api for generating the private key.
+ Returns:
+ account (Account): Newly created Ethereum account.
+ """
+ if qrng:
+ raise NotImplementedError
+ secret = hex(random.getrandbits(256))
+ return self._create_account(secret)
+
+ def recover(self, secret: str) -> Account:
+ """
+ Recovers an account from a secret.
+ Args:
+ secret (str): Account private key in hexadecimal string
+ Returns:
+ account (Account): Recovered Ethereum account.
+ """
+ if not secret or not len(secret) == 66:
+ raise PrivateKeyNotFoundException('Please provide account secret.')
+ return self._create_account(secret)
+
+ def parse_mnemonics(self, mnemonics: str) -> str:
+ """
+ Recovers an account secret from mnemonics phrase
+ Args:
+ mnemonics (str): BIP39 mnemonics phrase.
+ Returns:
+ secret (str): Account secret. Use `recover_account` to create a new account with this secret.
+ """
+ raise NotImplementedError
+
+ def sign(self, private_key: str, message: str) -> str:
"""
Use ECDSA to sign a message.
Args:
- address (str): Ethereum address of the wallet that will sign the message.
- data (str): Data to be signed, EITHER a hash string or a Transaction.
+ private_key (str): Must be either an address(20 byte) or an raw private key (32 byte)"}}'
+ message (str): Data to be hashed and signed. Dont input hashed data unless you know what you are doing.
Returns:
signed_message (str): ECDSA calculated r, s, and parity v, concatenated. v = 27 + (r % 2)
"""
- # in3_ret_t eth_sign(void* ctx, d_signature_type_t type, bytes_t message, bytes_t account, uint8_t* dst)
- # eth_sign(ctx, SIGN_EC_RAW, *data, bytes(NULL, 0), sig))
- # SIGN_EC_RAW = 0, /**< sign the data directly */ SIGN_EC_HASH = 1, /**< hash and sign the data */
- signature = bytearray()
- if isinstance(data, str):
- self._factory.get_hash(data)
- return_code = self._runtime.call(
- EthMethods.SIGN, 0, address, data, signature)
- elif isinstance(data, RawTransaction):
- raise NotImplementedError
- # TODO: This uses only the tx.data. Check with Shoaib. Should be a json of all filled in params
- # TODO: Move to in3_signData
- # return_code = self._runtime.call(EthMethods.SIGN, 1, address, data, None, signature)
- else:
- raise ValueError
- if return_code and return_code == 65:
- return str(signature)
- else:
- raise ClientException('Unknown error trying to sign the provided data.')
+ # SIGN_EC_RAW = 0, /**< sign the data directly
+ # SIGN_EC_HASH = 1, /**< hash and sign the data */
+ signature_type = 'eth_sign'
+ # in3_ret_t in3_sign_data(data, pk, sig_type)
+ signature_dict = self._runtime.call(EthMethods.SIGN, message, private_key, signature_type)
+ return signature_dict['signature']
+
+ def balance(self, address: str, at_block: int or str = str(BlockAt.LATEST)) -> int:
+ """
+ Returns the balance of the account of given address.
+ Args:
+ address (str): address to check for balance
+ at_block (int or str): block number IN3BlockNumber or EnumBlockStatus
+ Returns:
+ balance (int): integer of the current balance in wei.
+ """
+ account = self._factory.get_account(address)
+ if isinstance(at_block, int):
+ at_block = hex(at_block)
+ return self._factory.get_integer(self._runtime.call(EthMethods.BALANCE, account.address, at_block))
- def send_transaction(self, transaction: RawTransaction) -> str:
+ def send_transaction(self, sender: Account, transaction: NewTransaction) -> str:
"""
- Signs and sends the assigned transaction. Requires the 'key' value to be set in ClientConfig.
+ Signs and sends the assigned transaction. Requires `account.secret` value set.
Transactions change the state of an account, just the balance, or additionally, the storage and the code.
Every transaction has a cost, gas, paid in Wei. The transaction gas is calculated over estimated gas times the
gas cost, plus an additional miner fee, if the sender wants to be sure that the transaction will be mined in the
latest block.
Args:
- transaction: All information needed to perform a transaction. Minimum is from, to and value.
- Client will add the other required fields, gas and chaindId.
+ sender (Account): Sender Ethereum account. Senders generally pay the gas costs, so they must have enough balance to pay gas + amount sent, if any.
+ transaction (NewTransaction): All information needed to perform a transaction. Minimum is to and value. Client will add the other required fields, gas and chaindId.
Returns:
- tx_hash: Transaction hash, used to get the receipt and check if the transaction was mined.
+ tx_hash (hex): Transaction hash, used to get the receipt and check if the transaction was mined.
"""
- return self._runtime.call(EthMethods.SEND_TRANSACTION, transaction)
+ assert isinstance(transaction, NewTransaction)
+ assert isinstance(sender, Account)
+ if not sender.secret or not len(hex(sender.secret)) == 66:
+ raise AssertionError('To send a transaction, the sender\'s secret must be known by the application. \
+ To send a pre-signed transaction use `send_raw_transaction` instead.')
+ transaction.From = sender.address
+ self._runtime.set_signer_account(sender.secret)
+ return self._runtime.call(EthMethods.SEND_TRANSACTION, transaction.serialize())
- # TODO: Create Receipt domain object
- def get_transaction_receipt(self, tx_hash: str) -> dict:
- """
- After a transaction is received the by the client, it returns the transaction hash. With it, it is possible to
- gather the receipt, once a miner has mined and it is part of an acknowledged block. Because how it is possible,
- in distributed systems, that data is asymmetric in different parts of the system, the transaction is only "final"
- once a certain number of blocks was mined after it, and still it can be possible that the transaction is discarded
- after some time. But, in general terms, it is accepted that after 6 to 8 blocks from latest, that it is very
- likely that the transaction will stay in the chain.
+ def send_raw_transaction(self, signed_transaction: str) -> str:
+ """
+ Sends a signed and encoded transaction.
Args:
- tx_hash: Transaction hash.
+ signed_transaction: Signed keccak hash of the serialized transaction
+ Client will add the other required fields, gas and chaindId.
Returns:
- tx_receipt:
+ tx_hash (hex): Transaction hash, used to get the receipt and check if the transaction was mined.
"""
- return self._runtime.call(EthMethods.TRANSACTION_RECEIPT, self._factory.get_hash(tx_hash))
+ return self._runtime.call(EthMethods.SEND_RAW_TRANSACTION, signed_transaction)
- def estimate_gas(self, transaction: RawTransaction) -> int:
+ def estimate_gas(self, transaction: NewTransaction) -> int:
"""
Gas estimation for transaction. Used to fill transaction.gas field. Check RawTransaction docs for more on gas.
Args:
@@ -82,7 +129,25 @@ def estimate_gas(self, transaction: RawTransaction) -> int:
Returns:
gas (int): Calculated gas in Wei.
"""
- return self._runtime.call(EthMethods.ESTIMATE_TRANSACTION, transaction)
+ gas = self._runtime.call(EthMethods.ESTIMATE_TRANSACTION, transaction.serialize())
+ return self._factory.get_integer(gas)
+
+ def transaction_count(self, address: str, at_block: int or str = str(BlockAt.LATEST)) -> int:
+ """
+ Number of transactions mined from this address. Used to set transaction nonce.
+ Nonce is a value that will make a transaction fail in case it is different from (transaction count + 1).
+ It exists to mitigate replay attacks.
+ Args:
+ address (str): Ethereum account address
+ at_block (int): Block number
+ Returns:
+ tx_count (int): Number of transactions mined from this address.
+ """
+ account = self._factory.get_account(address)
+ if isinstance(at_block, int):
+ at_block = hex(at_block)
+ tx_count = self._runtime.call(EthMethods.TRANSACTION_COUNT, account.address, at_block)
+ return self._factory.get_integer(tx_count)
def checksum_address(self, address: str, add_chain_id: bool = True) -> str:
"""
@@ -94,4 +159,4 @@ def checksum_address(self, address: str, add_chain_id: bool = True) -> str:
Returns:
checksum_address: EIP-55 compliant, mixed-case address object.
"""
- return self._factory.checksum_address(self._factory.get_address(address).address, add_chain_id)
+ return self._factory.checksum_address(self._factory.get_account(address).address, add_chain_id)
diff --git a/python/in3/eth/api.py b/python/in3/eth/api.py
index 7fd1b158b..e906c680d 100644
--- a/python/in3/eth/api.py
+++ b/python/in3/eth/api.py
@@ -1,8 +1,9 @@
from in3.eth.account import EthAccountApi
+from in3.eth.contract import EthContractApi
from in3.eth.factory import EthObjectFactory
-from in3.eth.model import Transaction, Block
+from in3.eth.model import Transaction, Block, TransactionReceipt
+from in3.libin3.enum import EthMethods, BlockAt
from in3.libin3.runtime import In3Runtime
-from in3.libin3.enum import EthMethods, BlockStatus
class EthereumApi:
@@ -10,10 +11,11 @@ class EthereumApi:
Module based on Ethereum's api and web3.js
"""
- def __init__(self, runtime: In3Runtime, chain_id: str):
+ def __init__(self, runtime: In3Runtime):
self._runtime = runtime
- self.factory = EthObjectFactory(runtime, chain_id)
- self.account = EthAccountApi(runtime, self.factory)
+ self._factory = EthObjectFactory(runtime)
+ self.account = EthAccountApi(runtime, self._factory)
+ self.contract = EthContractApi(runtime, self._factory)
def keccak256(self, message: str) -> str:
"""
@@ -31,7 +33,7 @@ def gas_price(self) -> int:
Returns:
price (int): minimum gas value for the transaction to be mined
"""
- return self.factory.get_integer(self._runtime.call(EthMethods.GAS_PRICE))
+ return self._factory.get_integer(self._runtime.call(EthMethods.GAS_PRICE))
def block_number(self) -> int:
"""
@@ -41,64 +43,9 @@ def block_number(self) -> int:
Returns:
block_number (int) : Number of the most recent block
"""
- return self.factory.get_integer(self._runtime.call(EthMethods.BLOCK_NUMBER))
+ return self._factory.get_integer(self._runtime.call(EthMethods.BLOCK_NUMBER))
- def get_balance(self, address: str, at_block: int or str = str(BlockStatus.LATEST)) -> int:
- """
- Returns the balance of the account of given address.
- Args:
- address (str): address to check for balance
- at_block (int or str): block number IN3BlockNumber or EnumBlockStatus
- Returns:
- balance (int): integer of the current balance in wei.
- """
- account = self.factory.get_address(address)
- if isinstance(at_block, int):
- at_block = hex(at_block)
- return self.factory.get_integer(self._runtime.call(EthMethods.BALANCE, account.address, at_block))
-
- def get_storage_at(self, address: str, position: int = 0, at_block: int or str = BlockStatus.LATEST) -> str:
- """
- Stored value in designed position at a given address. Storage can be used to store a smart contract state, constructor or just any data.
- Each contract consists of a EVM bytecode handling the execution and a storage to save the state of the contract.
- The storage is essentially a key/value store. Use get_code to get the smart-contract code.
- Args:
- address (str): Ethereum account address
- position (int): Position index, 0x0 up to 0x64
- at_block (int or str): Block number
- Returns:
- storage_at (str): Stored value in designed position. Use decode('hex') to see ascii format of the hex data.
- """
- account = self.factory.get_address(address)
- return self._runtime.call(EthMethods.STORAGE_AT, account.address, position, at_block)
-
- def get_code(self, address: str, at_block: int or str = BlockStatus.LATEST) -> str:
- """
- Smart-Contract bytecode in hexadecimal. If the account is a simple wallet the function will return '0x'.
- Args:
- address (str): Ethereum account address
- at_block (int or str): Block number
- Returns:
- bytecode (str): Smart-Contract bytecode in hexadecimal.
- """
- account = self.factory.get_address(address)
- return self._runtime.call(EthMethods.CODE, account.address, at_block)
-
- def get_transaction_count(self, address: str, at_block: int or str = BlockStatus.LATEST) -> int:
- """
- Number of transactions mined from this address. Used to set transaction nonce.
- Nonce is a value that will make a transaction fail in case it is different from (transaction count + 1).
- It exists to mitigate replay attacks.
- Args:
- address (str): Ethereum account address
- at_block (int): Block number
- Returns:
- tx_count (int): Number of transactions mined from this address.
- """
- account = self.factory.get_address(address)
- return self._runtime.call(EthMethods.TRANSACTION_COUNT, account.address, at_block)
-
- def get_block_by_hash(self, block_hash: str, get_full_block: bool = False) -> Block:
+ def block_by_hash(self, block_hash: str, get_full_block: bool = False) -> BlockAt:
"""
Blocks can be identified by root hash of the block merkle tree (this), or sequential number in which it was mined (get_block_by_number).
Args:
@@ -107,10 +54,11 @@ def get_block_by_hash(self, block_hash: str, get_full_block: bool = False) -> Bl
Returns:
block (Block): Desired block, if exists.
"""
- serialized: dict = self._runtime.call(EthMethods.BLOCK_BY_HASH, self.factory.get_hash(block_hash), get_full_block)
- return self.factory.get_block(serialized)
+ serialized: dict = self._runtime.call(EthMethods.BLOCK_BY_HASH, self._factory.get_hash(block_hash),
+ get_full_block)
+ return self._factory.get_block(serialized)
- def get_block_by_number(self, block_number: [int or str], get_full_block: bool = False) -> Block:
+ def block_by_number(self, block_number: [int or str], get_full_block: bool = False) -> Block:
"""
Blocks can be identified by sequential number in which it was mined, or root hash of the block merkle tree (this) (get_block_by_hash).
Args:
@@ -119,12 +67,13 @@ def get_block_by_number(self, block_number: [int or str], get_full_block: bool =
Returns:
block (Block): Desired block, if exists.
"""
- if isinstance(block_number, str) and not block_number.upper() in [e.value for e in BlockStatus]:
- raise AssertionError('Block number must be an integer or \'latest\', \'earliest\', or \'pending\'')
- serialized: dict = self._runtime.call(EthMethods.BLOCK_BY_NUMBER, block_number, get_full_block)
- return self.factory.get_block(serialized)
+ if isinstance(block_number, str) and not block_number.lower() in [str(e) for e in BlockAt]:
+ raise AssertionError('Block number must be an integer.')
+ block_number_str = hex(block_number) if isinstance(block_number, int) else block_number
+ serialized: dict = self._runtime.call(EthMethods.BLOCK_BY_NUMBER, block_number_str, get_full_block)
+ return self._factory.get_block(serialized)
- def get_transaction_by_hash(self, tx_hash: str) -> Transaction:
+ def transaction_by_hash(self, tx_hash: str) -> Transaction:
"""
Transactions can be identified by root hash of the transaction merkle tree (this) or by its position in the block transactions merkle tree.
Every transaction hash is unique for the whole chain. Collision could in theory happen, chances are 67148E-63%.
@@ -133,5 +82,21 @@ def get_transaction_by_hash(self, tx_hash: str) -> Transaction:
Returns:
transaction: Desired transaction, if exists.
"""
- serialized: dict = self._runtime.call(EthMethods.TRANSACTION_BY_HASH, self.factory.get_hash(tx_hash))
- return self.factory.get_transaction(serialized)
+ serialized: dict = self._runtime.call(EthMethods.TRANSACTION_BY_HASH, self._factory.get_hash(tx_hash))
+ return self._factory.get_transaction(serialized)
+
+ def transaction_receipt(self, tx_hash: str) -> TransactionReceipt:
+ """
+ After a transaction is received the by the client, it returns the transaction hash. With it, it is possible to
+ gather the receipt, once a miner has mined and it is part of an acknowledged block. Because how it is possible,
+ in distributed systems, that data is asymmetric in different parts of the system, the transaction is only "final"
+ once a certain number of blocks was mined after it, and still it can be possible that the transaction is discarded
+ after some time. But, in general terms, it is accepted that after 6 to 8 blocks from latest, that it is very
+ likely that the transaction will stay in the chain.
+ Args:
+ tx_hash: Transaction hash.
+ Returns:
+ tx_receipt: The mined Transaction data including event logs.
+ """
+ tx_receipt = self._runtime.execute(EthMethods.TRANSACTION_RECEIPT, self._factory.get_hash(tx_hash))
+ return self._factory.get_tx_receipt(tx_receipt)
diff --git a/python/in3/eth/contract.py b/python/in3/eth/contract.py
new file mode 100644
index 000000000..32f442c39
--- /dev/null
+++ b/python/in3/eth/contract.py
@@ -0,0 +1,128 @@
+import re
+
+from in3.eth.factory import EthObjectFactory
+from in3.eth.model import NewTransaction, DataTransferObject
+from in3.libin3.enum import EthMethods, BlockAt, In3Methods
+from in3.libin3.runtime import In3Runtime
+
+
+class SmartContract(DataTransferObject):
+ """
+ Ethereum account containing smart-contract code.
+ Args:
+ address: Account address. Derived from public key.
+ chain_id: ID of the chain the account is used in.
+ abi: Contract methods ABI, used to call them via RPC. Parsed from json string.
+ code: EVM Bytecode for contract execution. Important for STANDARD and FULL verification.
+ secret: Account private key. A 256 bit number.
+ domain: ENS Domain name. ie. niceguy.eth
+ """
+
+ def __init__(self, address: str, chain_id: int, abi: dict, code: str = None, secret: int = None,
+ domain: str = None):
+ self.address = address
+ self.chain_id = chain_id
+ self.abi = abi
+ self.code = code
+ self.secret = secret
+ self.domain = domain
+
+ def __str__(self):
+ return self.address
+
+
+class EthContractApi:
+ """
+ Manages smart-contract data and transactions
+ """
+
+ def __init__(self, runtime: In3Runtime, factory: EthObjectFactory):
+ self._runtime = runtime
+ self._factory = factory
+
+ def call(self, transaction: NewTransaction, block_number: int or str = 'latest') -> int or str:
+ """
+ Calls a smart-contract method. Will be executed locally by Incubed's EVM or signed and sent over to save the state changes.
+ Check https://ethereum.stackexchange.com/questions/3514/how-to-call-a-contract-method-using-the-eth-call-json-rpc-api for more.
+ Args:
+ transaction (NewTransaction):
+ block_number (int or str): Desired block number integer or 'latest', 'earliest', 'pending'.
+ Returns:
+ method_returned_value: A hexadecimal. For decoding use in3.abi_decode.
+ """
+ # different than eth_call
+ # eth_call_fn(c, contract, BLKNUM_LATEST(), "servers(uint256):(string,address,uint,uint,uint,address)", to_uint256(i));
+ return self._runtime.call(EthMethods.CALL, transaction.serialize(), block_number)
+
+ def storage_at(self, address: str, position: int = 0, at_block: int or str = str(BlockAt.LATEST)) -> str:
+ """
+ Stored value in designed position at a given address. Storage can be used to store a smart contract state, constructor or just any data.
+ Each contract consists of a EVM bytecode handling the execution and a storage to save the state of the contract.
+ The storage is essentially a key/value store. Use get_code to get the smart-contract code.
+ Args:
+ address (str): Ethereum account address
+ position (int): Position index, 0x0 up to 0x64
+ at_block (int or str): Block number
+ Returns:
+ storage_at (str): Stored value in designed position. Use decode('hex') to see ascii format of the hex data.
+ """
+ account = self._factory.get_account(address)
+ if isinstance(at_block, int):
+ at_block = hex(at_block)
+ return self._runtime.call(EthMethods.STORAGE_AT, account.address, hex(position), at_block)
+
+ def code(self, address: str, at_block: int or str = str(BlockAt.LATEST)) -> str:
+ """
+ Smart-Contract bytecode in hexadecimal. If the account is a simple wallet the function will return '0x'.
+ Args:
+ address (str): Ethereum account address
+ at_block (int or str): Block number
+ Returns:
+ bytecode (str): Smart-Contract bytecode in hexadecimal.
+ """
+ account = self._factory.get_account(address)
+ if isinstance(at_block, int):
+ at_block = hex(at_block)
+ return self._runtime.call(EthMethods.CODE, account.address, at_block)
+
+ def encode(self, fn_signature: str, *fn_args) -> str:
+ """
+ Smart-contract ABI encoder. Used to serialize a rpc to the EVM.
+ Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
+ Note: Parameters refers to the list of variables in a method declaration.
+ Arguments are the actual values that are passed in when the method is invoked.
+ When you invoke a method, the arguments used must match the declaration's parameters in type and order.
+ Args:
+ fn_signature (str): Function name, with parameters. i.e. `getBalance(uint256):uint256`, can contain the return types but will be ignored.
+ fn_args (tuple): Function parameters, in the same order as in passed on to method_name.
+ Returns:
+ encoded_fn_call (str): i.e. "0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890"
+ """
+ self._check_fn_signature(fn_signature)
+ return self._runtime.call(In3Methods.ABI_ENCODE, fn_signature, fn_args)
+
+ def decode(self, fn_signature: str, encoded_value: str) -> tuple:
+ """
+ Smart-contract ABI decoder. Used to parse rpc responses from the EVM.
+ Based on the [Solidity specification.](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html)
+ Args:
+ fn_signature: Function signature. e.g. `(address,string,uint256)` or `getBalance(address):uint256`.
+ In case of the latter, the function signature will be ignored and only the return types will be parsed.
+ encoded_value: Abi encoded values. Usually the string returned from a rpc to the EVM.
+ Returns:
+ decoded_return_values (tuple): "0x1234567890123456789012345678901234567890", "0x05"
+ """
+ if not encoded_value.startswith('0x'):
+ raise AssertionError("Encoded values must start with 0x")
+ if len(encoded_value[2:]) < 64:
+ raise AssertionError("Encoded values must be longer than 64 characters.")
+ self._check_fn_signature(fn_signature)
+ return self._runtime.call(In3Methods.ABI_DECODE, fn_signature, encoded_value)
+
+ @staticmethod
+ def _check_fn_signature(fn_signature):
+ is_signature = re.match(r'.*(\(.+\))', fn_signature)
+ _types = ["address", "string", "uint", "string", "bool", "bytes", "int"]
+ contains_type = [_type for _type in _types if _type in fn_signature]
+ if not is_signature or not contains_type:
+ raise AssertionError('Function signature is not valid. A valid example is balanceOf(address).')
diff --git a/python/in3/eth/factory.py b/python/in3/eth/factory.py
index 19c87607b..5b3bbcbcb 100644
--- a/python/in3/eth/factory.py
+++ b/python/in3/eth/factory.py
@@ -1,17 +1,20 @@
+"""
+Ethereum Domain Object Factory
+For more on design-patterns see [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
+"""
+from in3.eth.model import Block, Transaction, Log, TransactionReceipt, Account
from in3.exception import HashFormatException, EthAddressFormatException
-from in3.eth.model import Block, Transaction, Account
from in3.libin3.enum import In3Methods
+from in3.libin3.runtime import In3Runtime
class EthObjectFactory:
"""
- Deserialize and instantiate objects from rpc responses
- For more on design-patterns see [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
+ Deserialize and instantiate marshalled objects from rpc responses
"""
- def __init__(self, runtime, chain_id: str):
+ def __init__(self, runtime: In3Runtime):
self._runtime = runtime
- self._chain_id = chain_id
def _deserialize(self, obj_dict: dict, mapping: dict) -> dict:
result = {}
@@ -29,24 +32,25 @@ def get_integer(self, hex_str: str) -> int:
def get_block(self, serialized: dict):
mapping = {
- "number": int,
+ "number": self.get_integer,
"hash": self.get_hash,
"parentHash": self.get_hash,
- "nonce": int,
+ "nonce": self.get_integer,
"sha3Uncles": str,
"logsBloom": str,
- "transactionsRoot": str,
- "stateRoot": str,
- "miner": self.get_address,
- "difficulty": int,
- "totalDifficulty": int,
+ "transactionsRoot": self.get_hash,
+ "stateRoot": self.get_hash,
+ "miner": str,
+ "author": str,
+ "difficulty": self.get_integer,
+ "totalDifficulty": self.get_integer,
"extraData": str,
- "size": int,
- "gasLimit": int,
- "gasUsed": int,
- "timestamp": int,
+ "size": self.get_integer,
+ "gasLimit": self.get_integer,
+ "gasUsed": self.get_integer,
+ "timestamp": self.get_integer,
# "transactions": [{...}, {...}],
- "uncles": list
+ # "uncles": list
}
obj = self._deserialize(serialized, mapping)
transactions = []
@@ -56,48 +60,100 @@ def get_block(self, serialized: dict):
aux = self.get_transaction(t)
transactions.append(aux)
else:
- # In case the user wants tx hashes only not full blocks
+ # In case the user wants tx hashes only not full txs
transactions.append(self.get_hash(t))
obj["transactions"] = transactions
+ uncles = []
+ if serialized["uncles"] is not None and len(serialized["uncles"]) > 0:
+ for t in serialized["uncles"]:
+ if type(t) is dict:
+ aux = self.get_block(t)
+ uncles.append(aux)
+ else:
+ # In case the user wants block hashes only not full blocks
+ uncles.append(self.get_hash(t))
+ obj["uncles"] = uncles
return Block(**obj)
- def get_transaction(self, serialized: dict):
+ def get_transaction(self, serialized: dict) -> Transaction:
mapping = {
"blockHash": self.get_hash,
- "from": self.get_address,
- "gas": int,
- "gasPrice": int,
+ # "from": self.get_address,
+ "gas": self.get_integer,
+ "gasPrice": self.get_integer,
"hash": self.get_hash,
"input": str,
- "nonce": int,
+ "nonce": self.get_integer,
"to": self.get_address,
- "transactionIndex": int,
- "value": int,
- "v": str,
- "r": str,
- "s": str
+ "transactionIndex": self.get_integer,
+ "value": self.get_integer,
+ "raw": str,
+ "standardV": self.get_integer,
+ "publicKey": str,
+ "creates": str,
+ "chainId": self.get_integer,
+ "v": self.get_integer,
+ "r": self.get_integer,
+ "s": self.get_integer
}
aux = self._deserialize(serialized, mapping)
aux["From"] = self.get_address(serialized["from"])
return Transaction(**aux)
+ def get_tx_receipt(self, serialized: dict) -> TransactionReceipt:
+ mapping = {
+ 'blockHash': self.get_hash,
+ 'blockNumber': self.get_integer,
+ 'contractAddress': self.get_address if serialized['contractAddress'] else None,
+ 'cumulativeGasUsed': self.get_integer,
+ 'gasUsed': self.get_integer,
+ 'logsBloom': str,
+ 'status': self.get_integer,
+ 'to': self.get_address if serialized['to'] else None,
+ 'transactionHash': self.get_hash,
+ 'transactionIndex': self.get_integer
+ }
+ obj = self._deserialize(serialized, mapping)
+ obj["From"] = self.get_address(serialized["from"])
+ if serialized["logs"] is not None and len(serialized["logs"]) > 0:
+ obj["logs"] = [self.get_log(log) for log in serialized["logs"]]
+ return TransactionReceipt(**obj)
+
+ def get_log(self, serialized: dict) -> Log:
+ mapping = {
+ 'address': self.get_address,
+ 'blockHash': self.get_integer,
+ 'blockNumber': self.get_integer,
+ 'data': str,
+ 'logIndex': self.get_integer,
+ 'removed': bool,
+ 'transactionHash': self.get_hash,
+ 'transactionIndex': self.get_integer,
+ 'transactionLogIndex': self.get_integer,
+ }
+ aux = self._deserialize(serialized, mapping)
+ aux["topics"] = [self.get_hash(topic) for topic in serialized["topics"]]
+ aux["Type"] = serialized["type"]
+ return Log(**aux)
+
def checksum_address(self, address: str, add_chain_id: bool = True) -> str:
return self._runtime.call(In3Methods.CHECKSUM_ADDRESS, address, add_chain_id)
- @staticmethod
- def get_hash(hash_str: str):
+ def get_hash(self, hash_str: str) -> str:
if not hash_str.startswith('0x'):
raise HashFormatException("Ethereum hashes start with 0x")
- if len(hash_str.encode('utf-8')) != 64:
+ if len(hash_str[2:].encode('utf-8')) != 64:
raise HashFormatException("Hash size is not of an Ethereum hash.")
return hash_str
- # TODO: Check if checksum address is working properly
- def get_address(self, address: str):
+ def get_address(self, address: str) -> str:
if not address.startswith("0x"):
raise EthAddressFormatException("Ethereum addresses start with 0x")
if len(address.encode("utf-8")) != 42:
raise EthAddressFormatException("The string don't have the size of an Ethereum address.")
- # if self.checksum_address(address, True) != address:
- # raise EthAddressFormatException("The string checksum is invalid for an Ethereum address.")
- return Account(address, self._chain_id)
+ if self.checksum_address(address, False) != address:
+ address = self.checksum_address(address, False)
+ return address.replace('\'', '"')
+
+ def get_account(self, address: str, secret: int = None) -> Account:
+ return Account(self.get_address(address), self._runtime.chain_id, secret)
diff --git a/python/in3/eth/model.py b/python/in3/eth/model.py
index 060536706..83481dfb6 100644
--- a/python/in3/eth/model.py
+++ b/python/in3/eth/model.py
@@ -1,58 +1,23 @@
-import enum
import json
class DataTransferObject:
"""
- Map marshalling objects transferred to and from a remote facade, in this case, libin3 rpc api.
+ Maps marshalling objects transferred to, and from a remote facade, in this case, libin3 rpc api.
For more on design-patterns see [Martin Fowler's](https://martinfowler.com/eaaCatalog/) Catalog of Patterns of Enterprise Application Architecture.
"""
- def to_dict(self) -> dict:
- # TODO: Refactor
- aux = self.__dict__
- result = {}
- for i in aux:
- if aux[i] is None:
- continue
-
- arr = i.split("_")
- r = ""
- index_aux = 0
- for arr_aux in arr:
- if arr_aux == '':
- continue
- r += arr_aux[index_aux].upper() + arr_aux[index_aux + 1:]
- key = r[0].lower() + r[1:]
-
- def get_val_from_object(_item) -> object:
- if isinstance(_item, enum.Enum):
- return _item.value
- # TODO: review or fix this policy
- elif type(_item) == int:
- return hex(int(_item))
- elif isinstance(_item, Account):
- return str(_item)
- elif issubclass(_item.__class__, DataTransferObject):
- return _item.to_dict()
- return _item
-
- if isinstance(aux[i], tuple):
- value = []
- for a in aux[i]:
- value.append(get_val_from_object(a))
- else:
- value = get_val_from_object(aux[i])
-
- result[key] = value
- return result
+ def to_dict(self, int_to_hex: bool = False) -> dict:
+ dictionary = {k: v for k, v in self.__dict__.items() if v is not None}
+ if int_to_hex:
+ integers = {k: hex(v) for k, v in dictionary.items() if isinstance(v, int)}
+ dictionary.update(integers)
+ return dictionary
def serialize(self) -> str:
- return json.dumps(self.to_dict(self))
+ return json.dumps(self.to_dict())
-# TODO: from - String|Number: The address for the sending account. Uses the web3.eth.defaultAccount property, if not specified. Or an address or index of a local wallet in web3.eth.accounts.wallet.
-# TODO: Check if setting gas limit is possible.
class Transaction(DataTransferObject):
"""
Args:
@@ -66,35 +31,40 @@ class Transaction(DataTransferObject):
nonce (int): Number of transactions mined from this address. Nonce is a value that will make a transaction fail in case it is different from (transaction count + 1). It exists to mitigate replay attacks. This allows to overwrite your own pending transactions by sending a new one with the same nonce. Use in3.eth.account.get_transaction_count to get the latest value.
hash (hex str): Keccak of the transaction bytes, not part of the transaction. Also known as receipt, because this field is filled after the transaction is sent, by eth_sendTransaction
blockHash (hex str): Block hash that this transaction was mined in. null when its pending.
- blockNumber (int): Block number that this transaction was mined in. null when its pending.
+ blockHash (int): Block number that this transaction was mined in. null when its pending.
transactionIndex (int): Integer of the transactions index position in the block. null when its pending.
signature (hex str): ECDSA of transaction.data, calculated r, s and v concatenated. V is parity set by v = 27 + (r % 2).
"""
- def __init__(self, From: str, to: str, gas: int, gasPrice: int, hash: str, data: str, nonce: int, gasLimit: int,
- blockNumber: int, transactionIndex: int, blockHash: str, value: int, signature: str):
+ def __init__(self, From: str, to: str, gas: int, gasPrice: int, hash: str, nonce: int, transactionIndex: int,
+ blockHash: str, value: int, input: str, publicKey: str, standardV: int, raw: str, creates: str,
+ chainId: int, r: int, s: int, v: int):
self.blockHash = blockHash
- self.blockNumber = blockNumber
- self.gasLimit = gasLimit
self.From = From
self.gas = gas
self.gasPrice = gasPrice
self.hash = hash
- self.data = data
self.nonce = nonce
self.to = to
self.transactionIndex = transactionIndex
self.value = value
- self.signature = signature
-
-
-class RawTransaction(DataTransferObject):
+ self.input = input
+ self.publicKey = publicKey
+ self.raw = raw
+ self.standardV = standardV
+ self.creates = creates
+ self.chainId = chainId
+ self.r = r
+ self.s = s
+ self.v = v
+
+
+class NewTransaction(DataTransferObject):
"""
Unsent transaction. Use to send a new transaction.
Args:
From (hex str): Address of the sender account.
to (hex str): Address of the receiver account. Left undefined for a contract creation transaction.
- gas (int): Gas for the transaction miners and execution in wei. Will get multiplied by `gasPrice`. Use in3.eth.account.estimate_gas to get a calculated value. Set too low and the transaction will run out of gas.
value (int): (optional) Value transferred in wei. The endowment for a contract creation transaction.
data (hex str): (optional) Either a ABI byte string containing the data of the function call on a contract, or in the case of a contract-creation transaction the initialisation code.
gasPrice (int): (optional) Price of gas in wei, defaults to in3.eth.gasPrice. Also know as `tx fee price`. Set your gas price too low and your transaction may get stuck. Set too high on your own loss.
@@ -104,10 +74,9 @@ class RawTransaction(DataTransferObject):
signature (hex str): (optional) ECDSA of transaction, r, s and v concatenated. V is parity set by v = 27 + (r % 2).
"""
- def __init__(self, From: str, to: str, gas: int, nonce: int, value: int = None, data: str = None,
- gasPrice: int = None, gasLimit: int = None, hash: str = None, signature: str = None):
+ def __init__(self, From: str = None, to: str = None, nonce: int = None, value: int = None,
+ data: str = None, gasPrice: int = None, gasLimit: int = None, hash: str = None, signature: str = None):
self.From = From
- self.gas = gas
self.gasPrice = gasPrice
self.gasLimit = gasLimit
self.hash = hash
@@ -116,6 +85,14 @@ def __init__(self, From: str, to: str, gas: int, nonce: int, value: int = None,
self.to = to
self.value = value
self.signature = signature
+ super().__init__()
+
+ def serialize(self) -> dict:
+ dictionary = self.to_dict(int_to_hex=True)
+ if 'From' in dictionary:
+ del dictionary['From']
+ dictionary['from'] = self.From
+ return dictionary
class Block(DataTransferObject):
@@ -123,8 +100,7 @@ class Block(DataTransferObject):
def __init__(self, number: int, hash: str, parentHash: str, nonce: int, sha3Uncles: list, logsBloom: str,
transactionsRoot: str, stateRoot: str, miner: str, difficulty: int, totalDifficulty: int,
extraData: str, size: int, gasLimit: int, gasUsed: int, timestamp: int, transactions: list,
- uncles: list):
-
+ uncles: list, author: str):
self.number = number
self.hash = hash
self.parentHash = parentHash
@@ -143,6 +119,7 @@ def __init__(self, number: int, hash: str, parentHash: str, nonce: int, sha3Uncl
self.timestamp = timestamp
self.transactions = transactions
self.uncles = uncles
+ self.author = author
class Filter(DataTransferObject):
@@ -160,15 +137,76 @@ def __init__(self, fromBlock: int or str, toBlock: int or str, address: str, top
self.blockhash = blockhash
-class Account:
+class Log(DataTransferObject):
+ """
+ Transaction Log for events and data returned from smart-contract method calls.
"""
- Ethereum address of a wallet or smart-contract
+
+ def __init__(self, address: hex, blockHash: hex, blockNumber: int, data: hex, logIndex: int, removed: bool,
+ topics: [hex], transactionHash: hex, transactionIndex: int, transactionLogIndex: int, Type: str):
+ self.address = address
+ self.blockHash = blockHash
+ self.blockNumber = blockNumber
+ self.data = data
+ self.logIndex = logIndex
+ self.removed = removed
+ self.topics = topics
+ self.transactionHash = transactionHash
+ self.transactionIndex = transactionIndex
+ self.transactionLogIndex = transactionLogIndex
+ self.Type = Type
+
+
+class TransactionReceipt(DataTransferObject):
+ """
+ Receipt from a mined transaction.
+ Args:
+ blockHash:
+ blockNumber:
+ cumulativeGasUsed: total amount of gas used by block
+ From:
+ gasUsed: amount of gas used by this specific transaction
+ logs:
+ logsBloom:
+ status: 1 if transaction succeeded, 0 otherwise.
+ transactionHash:
+ transactionIndex:
+ to: Account to which this transaction was sent. If the transaction was a contract creation this value is set to None.
+ contractAddress: Contract Account address created, f the transaction was a contract creation, or None otherwise.
+ """
+
+ def __init__(self, blockHash: hex, blockNumber: int, cumulativeGasUsed: int, From: str, gasUsed: int,
+ logsBloom: hex, status: int, transactionHash: hex, transactionIndex: int,
+ logs: [Log] = None, to: str = None, contractAddress: str = None):
+ self.blockHash = blockHash
+ self.blockNumber = blockNumber
+ self.cumulativeGasUsed = cumulativeGasUsed
+ self.From = From
+ self.gasUsed = gasUsed
+ self.logsBloom = logsBloom
+ self.status = status
+ self.transactionHash = transactionHash
+ self.transactionIndex = transactionIndex
+ self.logs = logs
+ self.to = to
+ self.contractAddress = contractAddress
+
+
+class Account(DataTransferObject):
+ """
+ An Ethereum account.
+ Args:
+ address: Account address. Derived from public key.
+ chain_id: ID of the chain the account is used in.
+ secret: Account private key. A 256 bit number.
+ domain: ENS Domain name. ie. niceguy.eth
"""
- def __init__(self, address: str, chain_id: str, secret: str = None):
+ def __init__(self, address: str, chain_id: int, secret: int = None, domain: str = None):
self.address = address
self.chain_id = chain_id
self.secret = secret
+ self.domain = domain
def __str__(self):
return self.address
diff --git a/python/in3/exception.py b/python/in3/exception.py
index 52594a819..c825c7aab 100644
--- a/python/in3/exception.py
+++ b/python/in3/exception.py
@@ -1,4 +1,3 @@
-
class IN3BaseException(Exception):
""" In3 Base Exception """
pass
diff --git a/python/in3/libin3/__init__.py b/python/in3/libin3/__init__.py
index e69de29bb..99088d637 100644
--- a/python/in3/libin3/__init__.py
+++ b/python/in3/libin3/__init__.py
@@ -0,0 +1,7 @@
+"""
+Shared Library Runtime module
+
+Loads `libin3` according to host hardware architecture and OS.
+Maps symbols, methods and types from the library.
+Encapsulates low-level rpc calls into a comprehensive runtime.
+"""
diff --git a/python/in3/libin3/enum.py b/python/in3/libin3/enum.py
index 10ff529ba..11073b1cd 100644
--- a/python/in3/libin3/enum.py
+++ b/python/in3/libin3/enum.py
@@ -1,18 +1,23 @@
-import enum
-
"""
-libin3 definitions
+Maps libin3 names, types and other definitions
"""
+import enum
@enum.unique
class SimpleEnum(enum.Enum):
+ """
+ Abstract stringify enum class
+ """
def __str__(self):
return self.value
class EthMethods(SimpleEnum):
+ """
+ Ethereum API methods
+ """
KECCAK = "web3_sha3"
ACCOUNTS = "eth_accounts"
BALANCE = "eth_getBalance"
@@ -38,7 +43,8 @@ class EthMethods(SimpleEnum):
UNCLE_BY_BLOCKHASH_AND_INDEX = "eth_getUncleByBlockHashAndIndex"
UNCLE_BY_BLOCKNUMBER_AND_INDEX = "eth_getUncleByBlockNumberAndIndex"
CODE = "eth_getCode"
- SIGN = "eth_sign"
+ # SIGN = "eth_sign"
+ SIGN = "in3_signData"
NEW_FILTER = "eth_newFilter"
NEW_BLOCK_FILTER = "eth_newBlockFilter"
NEW_PENDING_TRANSACTION_FILTER = "eth_newPendingTransactionFilter"
@@ -49,73 +55,63 @@ class EthMethods(SimpleEnum):
class In3Methods(SimpleEnum):
- CHECKSUM_ADDRESS = "in3_checksumAddress"
- SEND = "send"
- SIGN = "sign"
- CALL = "call"
- IN3_NODE_LIST = "in3_nodeList"
- IN3_SIGN = "in3_sign"
- IN3_STATS = "in3_stats"
+ """
+ Incubed API methods
+ """
+ CONFIGURE = "in3_config"
+ ECRECOVER = "in3_ecrecover"
+ ENSRESOLVE = "in3_ens"
+ SIGN = "in3_sign"
+ NODE_STATS = "in3_stats"
ABI_ENCODE = "in3_abiEncode"
ABI_DECODE = "in3_abiDecode"
- PK_2_ADDRESS = "pk2address"
- PK_2_PUBLIC = "pk2public"
- ECRECOVER = "ecrecover"
- CREATE_KEY = "createkey"
- KEY = "KEY"
- CONFIG = "in3_config"
+ GET_CONFIG = "in3_getConfig"
+ PK_2_PUBLIC = "in3_pk2address"
+ PK_2_ADDRESS = "in3_pk2address"
+ NODE_LIST = "in3_nodeList"
+ CHECKSUM_ADDRESS = "in3_checksumAddress"
-class BlockStatus(SimpleEnum):
+class RPCCode(enum.Enum):
+ """
+ Codes returned from libin3 RPC.
+ On success positive values (impl. defined) upto INT_MAX maybe returned
+ """
+ IN3_OK = 0 # Success
+ IN3_EUNKNOWN = -1 # Unknown error - usually accompanied with specific error msg
+ IN3_ENOMEM = -2 # No memory
+ IN3_ENOTSUP = -3 # Not supported
+ IN3_EINVAL = -4 # Invalid value
+ IN3_EFIND = -5 # Not found
+ IN3_ECONFIG = -6 # Invalid config
+ IN3_ELIMIT = -7 # Limit reached
+ IN3_EVERS = -8 # Version mismatch
+ IN3_EINVALDT = -9 # Data invalid, eg. invalid/incomplete JSON
+ IN3_EPASS = -10 # Wrong password
+ IN3_ERPC = -11 # RPC error (i.e. in3_ctx_t::error set)
+ IN3_ERPCNRES = -12 # RPC no response
+ IN3_EUSNURL = -13 # USN URL parse error
+ IN3_ETRANS = -14 # Transport error
+ IN3_ERANGE = -15 # Not in range
+ IN3_WAITING = -16 # the process can not be finished since we are waiting for responses
+ IN3_EIGNORE = -17 # Ignorable error
+ IN3_EPAYMENT_REQUIRED = -18 # payment required
+
+
+class BlockAt(SimpleEnum):
+ """
+ Alias for Ethereum blocks
+ """
EARLIEST = "earliest"
LATEST = "latest"
PENDING = "pending"
class In3ProofLevel(SimpleEnum):
+ """
+ Alias for verification levels.
+ Verification is done by calculating Ethereum Trie states requested by the Incubed network ans signed as proofs of a certain state.
+ """
NONE = "none"
STANDARD = "standard"
FULL = "full"
-
-
-class Chain(SimpleEnum):
- MAINNET = dict(
- registry="0x2736D225f85740f42D17987100dc8d58e9e16252",
- chain_id="0x1",
- alias="mainnet",
- status="https://libs.slock.it?n=mainnet",
- node_list="https://libs.slock.it/mainnet/nd-3")
-
- KOVAN = dict(
- registry="0x27a37a1210df14f7e058393d026e2fb53b7cf8c1",
- chain_id="0x2a",
- alias="kovan",
- status="https://libs.slock.it?n=kovan",
- node_list="https://libs.slock.it/kovan/nd-3")
-
- EVAN = dict(
- registry="0x85613723dB1Bc29f332A37EeF10b61F8a4225c7e",
- chain_id="0x4b1",
- alias="evan",
- status="https://libs.slock.it?n=evan",
- node_list="https://libs.slock.it/evan/nd-3")
-
- GOERLI = dict(
- registry="0x85613723dB1Bc29f332A37EeF10b61F8a4225c7e",
- chain_id="0x5",
- alias="goerli",
- status="https://libs.slock.it?n=goerli",
- node_list="https://libs.slock.it/goerli/nd-3")
-
- IPFS = dict(
- registry="0xf0fb87f4757c77ea3416afe87f36acaa0496c7e9",
- chain_id="0x7d0",
- alias="ipfs",
- status="https://libs.slock.it?n=ipfs",
- node_list="https://libs.slock.it/ipfs/nd-3")
-
- def __str__(self):
- return self.value['alias']
-
- def __hex__(self):
- return self.value['chain_id']
diff --git a/python/in3/libin3/lib_loader.py b/python/in3/libin3/lib_loader.py
index e7e58ccc4..b4aa3ca49 100644
--- a/python/in3/libin3/lib_loader.py
+++ b/python/in3/libin3/lib_loader.py
@@ -1,128 +1,103 @@
"""
-Load libin3 shared library for the current system, map function signatures, map and set transport functions.
+Load libin3 shared library for the current system, map function ABI, sets in3 network transport functions.
Example of RPC to In3-Core library, In3 Network and back.
```
+----------------+ +----------+ +------------+ +------------------+
-| | in3.client.eth.block_number() | | in3_client_exec_req | | In3 Network Request | |e
+| | in3.client.eth.block_number() | | in3_client_rpc | | In3 Network Request | |e
| python +------------------------------>+ python +-----------------------> libin3 +------------------------> python |
| application | | in3 | | in3-core | | http_transport |
| <-------------------------------+ <-----------------------+ <------------------------+ |
+----------------+ primitive or Object +----------+ ctype object +------------+ in3_req_add_response +------------------+
```
"""
-from ctypes import POINTER, CFUNCTYPE
-from ctypes import c_char, c_int, c_void_p, c_uint32, c_char_p, c_bool
-from ctypes import Structure, string_at, cast, cdll
-from pathlib import Path
-
-import math
+import ctypes as c
import platform
-import requests
-
-DEBUG: bool = False
-TIMEOUT = 5000
-
-class In3Request(Structure):
- """
- Request sent by the libin3 to the In3 Network, transported over the _http_transport function
- Based on in3/client/.h in3_request_t struct
- Attributes:
- payload (str): the payload to send
- urls ([str]): array of urls
- urls_len (int): number of urls
- results (str): the responses
- timeout (int): the timeout 0= no timeout
- times (int): measured times (in ms) which will be used for ajusting the weights
- """
- _fields_ = [("payload", POINTER(c_char)),
- ("urls", POINTER(POINTER(c_char))),
- ("urls_len", c_int),
- ("results", c_void_p),
- ("timeout", c_uint32),
- ("times", POINTER(c_uint32))]
+from pathlib import Path
-def libin3_new(timeout: int):
+def libin3_new(chain_id: int, transport: c.CFUNCTYPE, debug=False) -> int:
"""
- RPC to free libin3 objects in memory.
+ Instantiate new In3 Client instance.
Args:
- timeout (int): Time in milliseconds for http requests to fail due to timeout
+ chain_id (int): Chain id as integer
+ transport: Transport function for the in3 network requests
+ debug: Turn on debugger logging
Returns:
- instance (int): Memory address of the shared library instance, return value from libin3_new
+ instance (int): Memory address of the client instance, return value from libin3_new
"""
- global TIMEOUT
- TIMEOUT = float(timeout * math.pow(10, -3))
- return libin3.in3_new()
+ assert isinstance(chain_id, int)
+ global libin3
+ _map_function_signatures()
+ # define this function as the transport for in3 requests from client to server and back
+ libin3.in3_set_default_transport(transport)
+ # register transport and verifiers (needed only once)
+ libin3.in3_register_eth_full()
+ # TODO: IPFS libin3.in3_register_ipfs();
+ libin3.in3_register_eth_api()
+ # TODO: in3_set_storage_handler(c, storage_get_item, storage_set_item, storage_clear, NULL);
+ # enable logging
+ if debug:
+ # set logger level to TRACE
+ libin3.in3_log_set_quiet_(False)
+ libin3.in3_log_set_level_(0)
+ return libin3.in3_for_chain_auto_init(chain_id)
def libin3_free(instance: int):
"""
- RPC to free libin3 objects in memory.
+ Free In3 Client objects from memory.
Args:
- instance (int): Memory address of the shared library instance, return value from libin3_new
+ instance (int): Memory address of the client instance, return value from libin3_new
"""
libin3.in3_free(instance)
-def libin3_call(instance: int, rpc: bytes):
+def libin3_exec(instance: int, rpc: bytes):
"""
- Make Remote Procedure Call to an arbitrary method of a libin3 instance
+ Make Remote Procedure Call mapped methods in the client.
Args:
- instance (int): Memory address of the shared library instance, return value from libin3_new
- rpc (bytes): Serialized function call, a ethreum api json string.
+ instance (int): Memory address of the client instance, return value from libin3_new
+ rpc (bytes): Serialized function call, a json string.
Returns:
returned_value (object): The returned function value(s)
"""
ptr_res = libin3.in3_client_exec_req(instance, rpc)
- result = cast(ptr_res, c_char_p).value
+ result = c.cast(ptr_res, c.c_char_p).value
libin3._free_(ptr_res)
return result
-def _transport_report_success(in3_request: In3Request, i: int, response: requests.Response):
- libin3.in3_req_add_response(
- in3_request.results, i, False, response.content, -1)
-
-
-def _transport_report_failure(in3_request: In3Request, i: int, err: Exception):
- libin3.in3_req_add_response(in3_request.results, i, True, str(err), -1)
+def libin3_call(instance: int, fn_name: bytes, fn_args: bytes) -> (str, str):
+ """
+ Make Remote Procedure Call to an arbitrary method of a libin3 instance
+ Args:
+ instance (int): Memory address of the client instance, return value from libin3_new
+ fn_name (bytes): Name of function that will be called in the client rpc.
+ fn_args: (bytes) Serialized list of arguments, matching the parameters order of this function. i.e. ['0x123']
+ Returns:
+ result (int): Function execution status.
+ """
+ response = c.c_char_p()
+ error = c.c_char_p()
+ result = libin3.in3_client_rpc(instance, fn_name, fn_args, c.byref(response), c.byref(error))
+ return result, response.value, error.value
-def _http_transport(in3_request: In3Request):
+def libin3_set_pk(instance: int, private_key: bytes):
"""
- Transports each request coming from libin3 to the in3 network and and reports the answer back
+ Register the signer module in the In3 Client instance, with selected private key loaded in memory.
Args:
- in3_request (In3Request): request sent by the In3 Client Core to the In3 Network
- Returns:
- exit_status (int): Always zero for signaling libin3 the function executed OK.
+ instance (int): Memory address of the client instance, return value from libin3_new
+ private_key: 256 bit number.
"""
- in3_request = in3_request.contents
-
- for i in range(0, in3_request.urls_len):
- try:
- rpc_request = {
- 'url': string_at(in3_request.urls[i]),
- 'data': string_at(in3_request.payload),
- 'headers': {'Content-type': 'application/json'},
- 'timeout': TIMEOUT
- }
- response = requests.post(**rpc_request)
- response.raise_for_status()
- _transport_report_success(in3_request, i, response)
- except requests.exceptions.RequestException as err:
- _transport_report_failure(in3_request, i, err)
- except requests.exceptions.SSLError as err:
- _transport_report_failure(in3_request, i, err)
- except Exception as err:
- _transport_report_failure(in3_request, i, err)
- return 0
-
-
-def _multi_platform_selector():
+ libin3.eth_set_pk_signer_hex(instance, private_key)
+
+
+def _multi_platform_selector(prefix: str) -> str:
"""
- Helper to define the path of installed shared libraries. In this case libin3.
+ Helper to define the path of installed shared libraries.
Returns:
libin3_file_path (pathlib.Path): Path to the correct library, compiled to the current platform.
"""
@@ -133,80 +108,75 @@ def fail():
raise OSError('Not available on this platform ({}, {}, {}).'.format(
system, processor, machine))
- # TODO: Similar behavior could be achieved with regex expressions if we known them better.
-
+ # Fail over
if not processor:
processor = 'i386'
-
- extension = None
+ # Similar behavior could be achieved with regex expressions if we known them better.
+ suffix = None
if processor == 'i386' or 'Intel' in processor:
# AMD64 x86_64 64bit ...
if '64' in machine:
if system == 'Windows':
- extension = "x64.dll"
+ suffix = "x64.dll"
elif system == "Linux":
- extension = "x64.so"
+ suffix = "x64.so"
elif system == 'Darwin':
- extension = "x64.dylib"
+ suffix = "x64.dylib"
elif '32' in machine or '86' in machine:
if system == 'Windows':
fail()
elif system == "Linux":
- extension = "x32.so"
+ suffix = "x86.so"
elif system == 'Darwin':
fail()
elif 'armv' in machine:
- extension = 'arm7.so'
+ suffix = 'arm7.so'
elif 'ARM' in processor:
if machine == 'ARM7':
- extension = 'arm7.so'
-
- if not extension:
+ suffix = 'arm7.so'
+ if not suffix:
fail()
-
- if system == 'Windows':
- return Path(path.parent, "libin3", "shared", "in3.{}".format(extension))
- elif DEBUG:
- # Debug only available on mac.
- # If you need to it run on your system, run in3-core/scripts/build_debug.sh to get a build.
- # Then add it to libin3/shared folder
- return Path(path.parent, "libin3", "shared", "libin3d.{}".format(extension))
- else:
- return Path(path.parent, "libin3", "shared", "libin3.{}".format(extension))
-
-
-# =================== LIBIN3 SHARED LIBRARY MAPPING ===================
-libin3 = cdll.LoadLibrary(_multi_platform_selector())
-# map free
-libin3._free_.argtypes = c_void_p,
-libin3._free_.restype = None
-# map new in3
-libin3.in3_new.argtypes = []
-libin3.in3_new.restype = c_void_p
-# map free in3
-libin3.in3_free.argtypes = c_void_p,
-libin3.in3_free.restype = None
-# map transport request function
-libin3.in3_client_exec_req.argtypes = [c_void_p, c_char_p]
-libin3.in3_client_exec_req.restype = c_void_p
-# map transport function for response
-libin3.in3_req_add_response.argtypes = [
- c_void_p, c_int, c_bool, c_void_p, c_int]
-libin3.in3_req_add_response.restype = None
-# create a transport function pointer
-transport_fn = CFUNCTYPE(c_int, POINTER(In3Request))(_http_transport)
-# define this function as default transport for in3 requests from client to server and back
-libin3.in3_set_default_transport(transport_fn)
-# register transport and verifiers (needed only once)
-libin3.in3_register_eth_full()
-libin3.in3_register_eth_api()
-# enable logging
-if DEBUG:
+ return str(Path(path.parent, "libin3", "shared", "{}.{}".format(prefix, suffix)))
+
+
+def _map_function_signatures():
+ # =================== LIBIN3 SHARED LIBRARY MAPPING ===================
+ global libin3
+ # map new in3
+ libin3.in3_for_chain_auto_init.argtypes = [c.c_int]
+ libin3.in3_for_chain_auto_init.restype = c.c_void_p
+ libin3.in3_for_chain_default.argtypes = [c.c_int]
+ libin3.in3_for_chain_default.restype = c.c_void_p
+ # map free in3
+ libin3.in3_free.argtypes = c.c_void_p,
+ libin3.in3_free.restype = None
+ libin3._free_.argtypes = c.c_void_p,
+ libin3._free_.restype = None
+ # map set pk signer
+ libin3.eth_set_pk_signer_hex.argtypes = [c.c_void_p, c.c_char_p]
+ libin3.eth_set_pk_signer_hex.restype = None
+ # map transport request function
+ libin3.in3_client_exec_req.argtypes = [c.c_void_p, c.c_char_p]
+ libin3.in3_client_exec_req.restype = c.c_void_p
+ libin3.in3_client_rpc.argtypes = [c.c_void_p, c.c_char_p, c.c_char_p,
+ c.POINTER(c.c_char_p),
+ c.POINTER(c.c_char_p)]
+ libin3.in3_client_rpc.restype = c.c_int
+ # map transport function for response
+ libin3.in3_req_add_response.argtypes = [c.c_void_p, c.c_int, c.c_bool, c.c_char_p, c.c_int]
+ libin3.in3_req_add_response.restype = None
# map logging functions
- libin3.in3_log_set_quiet_.argtypes = c_bool,
+ libin3.in3_log_set_quiet_.argtypes = c.c_bool,
libin3.in3_log_set_quiet_.restype = None
- libin3.in3_log_set_level_.argtypes = c_int,
+ libin3.in3_log_set_level_.argtypes = c.c_int,
libin3.in3_log_set_level_.restype = None
- # set logger level to TRACE
- libin3.in3_log_set_quiet_(False)
- libin3.in3_log_set_level_(0)
+
+
+def init():
+ """
+ Loads library depending on host system.
+ """
+ return c.cdll.LoadLibrary(_multi_platform_selector('libin3'))
+
+
+libin3 = init()
diff --git a/python/in3/libin3/runtime.py b/python/in3/libin3/runtime.py
index 62c4a5a1d..80f2fa01f 100644
--- a/python/in3/libin3/runtime.py
+++ b/python/in3/libin3/runtime.py
@@ -1,11 +1,16 @@
+"""
+Encapsulates low-level rpc calls into a comprehensive runtime.
+"""
+import ctypes as c
import json
-
from enum import Enum
+
from in3.exception import ClientException
-from in3.libin3.lib_loader import libin3_new, libin3_free, libin3_call
+from in3.libin3.enum import RPCCode
+from in3.libin3.lib_loader import libin3_new, libin3_free, libin3_call, libin3_exec, libin3_set_pk
-class RPCRequest:
+class RPCExecRequest:
"""
RPC request to libin3
Args:
@@ -39,7 +44,7 @@ def __bytes__(self):
}).encode('utf8')
-class RPCResponse:
+class RPCExecResponse:
"""
RPC response from libin3.
Args:
@@ -56,20 +61,64 @@ def __init__(self, id: str, jsonrpc: str, result: str = None, error: str = None)
self.error = error
+class RPCCallRequest:
+ """
+ RPC request to libin3
+ Args:
+ fn_name: Name of function that will be called in libin3
+ fn_args: Arguments matching the parameters order of this function
+ """
+
+ def __init__(self, fn_name: str or Enum, fn_args: tuple = None, formatted: bool = False):
+ self.fn_name = str(fn_name).encode('utf8')
+ if fn_args and formatted:
+ self.fn_args = fn_args[0].encode('utf8')
+ elif fn_args and not formatted:
+ self.fn_args = json.dumps(list(fn_args)).replace('\'', '').encode('utf8')
+ else:
+ self.fn_args = '[]'.encode('utf8')
+
+
class In3Runtime:
"""
Instantiate libin3 and frees it when garbage collected.
Args:
- timeout (int): Time for http request connection and content timeout in milliseconds
+ chain_id (int): Chain-id based on EIP-155. If None provided, will connect to the Ethereum network. i.e: 0x1 for mainNet
"""
- def __init__(self, timeout: int):
- self.in3 = libin3_new(timeout)
+ def __init__(self, chain_id: int, transport: c.CFUNCTYPE):
+ self.in3 = libin3_new(chain_id, transport)
+ self.chain_id = chain_id
def __del__(self):
libin3_free(self.in3)
- def call(self, fn_name: str or Enum, *args) -> str or dict:
+ def call(self, fn_name: str or Enum, *fn_args, formatted: bool = False) -> str or dict:
+ """
+ Make a remote procedure call to a function in libin3
+ Args:
+ fn_name (str or Enum): Name of the function to be called
+ fn_args: Arguments matching the parameters order of this function
+ formatted (bool): True if args must be sent as-is to RPC endpoint
+ Returns:
+ fn_return (str): String of values returned by the function, if any.
+ """
+ request = RPCCallRequest(fn_name, fn_args, formatted)
+ result, response, error = libin3_call(self.in3, request.fn_name, request.fn_args)
+ in3_code = RPCCode(result)
+ if not in3_code == RPCCode.IN3_OK or error:
+ raise ClientException(str(error))
+ return json.loads(response)
+
+ def set_signer_account(self, secret: int) -> int:
+ """
+ Load an account secret to sign Ethereum transactions with `eth_sendTransaction` and `eth_call`.
+ Args:
+ secret: SK 256 bit number. example: int(0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7, 16)
+ """
+ return libin3_set_pk(self.in3, hex(secret).encode('utf8'))
+
+ def execute(self, fn_name: str or Enum, *args) -> str or dict:
"""
Make a remote procedure call to a function in libin3
Args:
@@ -78,11 +127,12 @@ def call(self, fn_name: str or Enum, *args) -> str or dict:
Returns:
fn_return (str): String of values returned by the function, if any.
"""
- request = RPCRequest(str(fn_name), args=args)
+ request = RPCExecRequest(str(fn_name), args=args)
request_bytes = bytes(request)
- response_bytes = libin3_call(self.in3, rpc=request_bytes)
- response_dict = json.loads(response_bytes.decode('utf8').replace('\n', ' '))
- response = RPCResponse(**response_dict)
- if response.error is not None:
- raise ClientException(response.error)
+ response_bytes = libin3_exec(self.in3, rpc=request_bytes)
+ response_str = response_bytes.decode('utf8').replace('\n', ' ')
+ if 'error' in response_str:
+ raise ClientException(response_str)
+ response_dict = json.loads(response_str)
+ response = RPCExecResponse(**response_dict)
return response.result
diff --git a/python/in3/libin3/shared/libin3.arm7.so b/python/in3/libin3/shared/libin3.arm7.so
index 954f05cbb..8a74b4025 100755
Binary files a/python/in3/libin3/shared/libin3.arm7.so and b/python/in3/libin3/shared/libin3.arm7.so differ
diff --git a/python/in3/libin3/shared/libin3.x32.so b/python/in3/libin3/shared/libin3.x32.so
deleted file mode 100755
index 9648f4d9e..000000000
Binary files a/python/in3/libin3/shared/libin3.x32.so and /dev/null differ
diff --git a/python/in3/libin3/shared/libin3.x64.dll b/python/in3/libin3/shared/libin3.x64.dll
new file mode 100644
index 000000000..cb104a169
Binary files /dev/null and b/python/in3/libin3/shared/libin3.x64.dll differ
diff --git a/python/in3/libin3/shared/libin3.x64.dylib b/python/in3/libin3/shared/libin3.x64.dylib
index 0c82ecfd9..c7e147510 100755
Binary files a/python/in3/libin3/shared/libin3.x64.dylib and b/python/in3/libin3/shared/libin3.x64.dylib differ
diff --git a/python/in3/libin3/shared/libin3.x64.so b/python/in3/libin3/shared/libin3.x64.so
index e0cc5b4ae..d8ab1da9d 100755
Binary files a/python/in3/libin3/shared/libin3.x64.so and b/python/in3/libin3/shared/libin3.x64.so differ
diff --git a/python/in3/libin3/shared/libin3.x86.so b/python/in3/libin3/shared/libin3.x86.so
new file mode 100755
index 000000000..8b8f34450
Binary files /dev/null and b/python/in3/libin3/shared/libin3.x86.so differ
diff --git a/python/in3/libin3/shared/libin3d.x64.dylib b/python/in3/libin3/shared/libin3d.x64.dylib
deleted file mode 100755
index b649418c2..000000000
Binary files a/python/in3/libin3/shared/libin3d.x64.dylib and /dev/null differ
diff --git a/python/in3/model.py b/python/in3/model.py
index dae55cefc..00dc113d6 100644
--- a/python/in3/model.py
+++ b/python/in3/model.py
@@ -1,5 +1,9 @@
+"""
+MVC Pattern Model domain classes for the Incubed client module
+"""
+import warnings
+
from in3.eth.model import DataTransferObject, Account
-from in3.libin3.enum import In3ProofLevel, Chain
class In3Node(DataTransferObject):
@@ -51,112 +55,128 @@ def __init__(self, nodes: [In3Node], contract: Account, registryId: str, lastBlo
class ClientConfig(DataTransferObject):
"""
- In3 Client Configuration class.
- Determines the behavior of client, which chain to connect to, verification policy, update cycle, minimum number of
- signatures collected on every request, and response timeout.
- Those are the settings that determine information security levels. Considering integrity is guaranteed by and
- confidentiality is not available on public blockchains, these settings will provide a balance between availability,
- and financial stake in case of repudiation. The "newer" the block is, or the closest to "latest", the higher are
- the chances it gets repudiated (a fork) by the chain, making lower the chances a node will sign on such information
- and thus reducing its availability. Up to a certain point, the older the block gets, the highest is its
- availability because of the close-to-zero repudiation risk. Blocks older than circa one year are stored in Archive
- Nodes, expensive computers, so, despite of the zero repudiation risk, there are not many nodes and they must search
- for the requested block in its database, lowering the availability as well. The verification policy enforces an
- extra step of security, that proves important in case you have only one response from an archive node
- and want to run a local integrity check, just to be on the safe side.
+ Determines the behavior of the in3 client, which chain to connect to and how to manage information security policies.
+
+ Considering integrity is guaranteed and confidentiality is not available on public blockchains, these settings will provide a balance between availability, and financial stake in case of repudiation.
+
+ The newer the block is, higher are the chances it gets repudiated by a fork in the chain. In3 nodes will decide individually to sign on repudiable information, reducing the availability. If the application needs the very latest block, consider using a calculated value in `node_signature_consensus` and set `node_signatures` to zero. This setting is as secure as a light-client.
+
+ The older the block gets, the highest is its availability because of the close-to-zero repudiation risk, but blocks older than circa one year are stored in Archive Nodes, expensive computers, so, despite of the low risk, there are not many nodes available with such information, and they must search for the requested block in its database, lowering the availability as well. If the application needs access to _old_ blocks, consider setting `request_timeout` and `request_retries` to accomodate the time the archive nodes take to fetch the inforamtion.
+
+ The verification policy enforces an extra step of security, adding a financial stake in case of repudiation or false/broken proof. For high security application, consider setting a calculated value in `node_min_deposit` and request as much signatures as necessary in `node_signatures`. Setting `chain_finality_threshold` high will guarantee non-repudiability.
+
+ **All args are Optional. Defaults connect to Ethereum main network with regular security levels.**
Args:
- chainId (str): (optional) - servers to filter for the given chain. The chain-id based on EIP-155. example: 0x1
- replaceLatestBlock (int): (optional) - if specified, the blocknumber latest will be replaced by blockNumber- specified value example: 6
- signatureCount (int): (optional) - number of signatures requested example: 2
- finality (int): (optional) - the number in percent needed in order reach finality (% of signature of the validators) example: 50
- minDeposit (int): - min stake of the server. Only nodes owning at least this amount will be chosen.
- proof :'none'|'standard'|'full' (optional) - if true the nodes should send a proof of the response
- autoUpdateList (bool): (optional) - if true the nodelist will be automatically updated if the lastBlock is newer
- timeout (int): specifies the number of milliseconds before the request times out. increasing may be helpful if the device uses a slow connection. example: 100000
- key (str): (optional) - the client key to sign requests example: 0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7
- includeCode (bool): (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
- maxAttempts (int): (optional) - max number of attempts in case a response is rejected example: 10
- keepIn3 (bool): (optional) - if true, the in3-section of thr response will be kept. Otherwise it will be removed after validating the data. This is useful for debugging or if the proof should be used afterwards.
- maxBlockCache (int): (optional) - number of number of blocks cached in memory example: 100
- maxCodeCache (int): (optional) - number of max bytes used to cache the code in memory example: 100000
- nodeLimit (int): (optional) - the limit of nodes to store in the client. example: 150
- requestCount (int): - Useful to be higher than 1 when using signatureCount <= 1. Then the client check for consensus in answers.
+ chain_finality_threshold (int): Behavior depends on the chain consensus algorithm: POA - percent of signers needed in order reach finality (% of the validators) i.e.: 60 %. POW - mined blocks on top of the requested, i.e. 8 blocks. Defaults are defined in enum.Chain.
+ latest_block_stall (int): Distance considered safe, consensus wise, from the very latest block. Higher values exponentially increases state finality, and therefore data security, as well guaranteeded responses from in3 nodes. example: 10 - will ask for the state from (latestBlock-10).
+ account_secret (str): Account SK to sign all in3 requests. (Experimental use `set_account_sk`) example: 0x387a8233c96e1fc0ad5e284353276177af2186e7afa85296f106336e376669f7
+ node_signatures (int): Node signatures attesting the response to your request. Will send a separate request for each. example: 3 nodes will have to sign the response.
+ node_signature_consensus (int): Useful when signatureCount <= 1. The client will check for consensus in responses. example: 10 - will ask for 10 different nodes and compare results looking for a consensus in the responses.
+ node_min_deposit (int): Only nodes owning at least this amount will be chosen to sign responses to your requests. i.e. 1000000000000000000 Wei
+ node_list_auto_update (bool): If true the nodelist will be automatically updated. False may compromise data security.
+ node_limit (int): Limit nodes stored in the client. example: 150 nodes
+ request_timeout (int): Milliseconds before a request times out. example: 100000 ms
+ request_retries (int): Maximum times the client will retry to contact a certain node. example: 10 retries
+ response_proof_level (str): 'none'|'standard'|'full' Full gets the whole block Patricia-Merkle-Tree, Standard only verifies the specific tree branch concerning the request, None only verifies the root hashes, like a light-client does.
+ response_includes_code (bool): If true, every request with the address field will include the data, if existent, that is stored in that wallet/smart-contract. If false, only the code digest is included.
+ response_keep_proof (bool): If true, proof data will be kept in every rpc response. False will remove this data after using it to verify the responses. Useful for debugging and manually verifying the proofs.
+ cached_blocks (int): Maximum blocks kept in memory. example: 100 last requested blocks
+ cached_code_bytes (int): Maximum number of bytes used to cache EVM code in memory. example: 100000 bytes
+ in3_registry (dict): In3 Registry Smart Contract configuration data
"""
- def __init__(self, chainId: str = str(Chain.MAINNET), key: str = None, replaceLatestBlock: int = 8,
- signatureCount: int = 3, finality: int = 70, minDeposit: int = 10000000000000000,
- proof: In3ProofLevel = In3ProofLevel.STANDARD, autoUpdateList: bool = True, timeout: int = 5000,
- includeCode: bool = False, keepIn3: bool = False, maxAttempts: int = None, maxBlockCache: int = None,
- maxCodeCache: int = None, nodeLimit: int = None, requestCount: int = 1):
- self.autoUpdateList: bool = autoUpdateList
- self.chainId: str = chainId
- self.finality: int = finality
- self.includeCode: bool = includeCode
- self.keepIn3: bool = keepIn3
- self.key: str = key
- self.timeout: int = timeout
- self.maxAttempts: int = maxAttempts
- self.maxBlockCache: int = maxBlockCache
- self.maxCodeCache: int = maxCodeCache
- self.minDeposit: int = minDeposit
- self.nodeLimit: int = nodeLimit
- self.proof: In3ProofLevel = proof
- self.replaceLatestBlock: int = replaceLatestBlock
- self.requestCount: int = requestCount
- self.signatureCount: int = signatureCount
-
-
-class TransactionReceipt(DataTransferObject):
-
- def __init__(self, transaction_hash: str, transaction_index: int, block_hash: str, block_number: int,
- _from: Account, to: Account, cumulative_gas_used: int, gas_used: int, contract_address: int,
- logs: list, logs_bloom: str):
- """
- bytes32_t transaction_hash; /**< the transaction hash */
- int transaction_index; /**< the transaction index */
- bytes32_t block_hash; /**< hash of ther containnig block */
- uint64_t block_number; /**< number of the containing block */
- uint64_t cumulative_gas_used; /**< total amount of gas used by block */
- uint64_t gas_used; /**< amount of gas used by this specific transaction */
- bytes_t* contract_address; /**< contract address created (if the transaction was a contract creation) or NULL */
- bool status; /**< 1 if transaction succeeded, 0 otherwise. */
- eth_log_t* logs; /**< array of log objects, which this transaction generated */
- Args:
- transaction_hash:
- transaction_index:
- block_hash:
- block_number:
- _from:
- to:
- cumulative_gas_used:
- gas_used:
- contract_address:
- logs:
- logs_bloom:
- """
- self.transaction_hash = transaction_hash
- self.transaction_index = transaction_index
- self.block_hash = block_hash
- self.block_number = block_number
- self._from = _from
- self.to = to
- self.cumulative_gas_used = cumulative_gas_used
- self.gas_used = gas_used
- self.contract_address = contract_address
- self.logs = logs
- self.logs_bloom = logs_bloom
-
-
-class Logs(DataTransferObject):
-
- def __init__(self, log_index: int, transaction_index: int, transaction_hash: str, block_hash: str,
- block_number: int, address: Account, data: str, topics: list):
- self.log_index = log_index
- self.transaction_index = transaction_index
- self.transaction_hash = transaction_hash
- self.block_hash = block_hash
- self.block_number = block_number
- self.address = address
- self.data = data
- self.topics = topics
+ def __init__(self,
+ chain_finality_threshold: int = None,
+ account_secret: str = None,
+ latest_block_stall: int = None,
+ node_signatures: int = None,
+ node_signature_consensus: int = None,
+ node_min_deposit: int = None,
+ node_list_auto_update: bool = None,
+ node_limit: int = None,
+ request_timeout: int = None,
+ request_retries: int = None,
+ response_proof_level: str = None,
+ response_includes_code: bool = None,
+ response_keep_proof: bool = None,
+ cached_blocks: int = None,
+ cached_code_bytes: int = None,
+ in3_registry: dict = None):
+ self.finality: int = chain_finality_threshold
+ self.key: str = account_secret
+ self.replaceLatestBlock: int = latest_block_stall
+ self.signatureCount: int = node_signatures
+ self.requestCount: int = node_signature_consensus
+ self.minDeposit: int = node_min_deposit
+ self.autoUpdateList: bool = node_list_auto_update
+ self.nodeLimit: int = node_limit
+ self.timeout: int = request_timeout
+ self.maxAttempts: int = request_retries
+ self.proof: str = response_proof_level
+ self.includeCode: bool = response_includes_code
+ self.keepIn3: bool = response_keep_proof
+ self.maxBlockCache: int = cached_blocks
+ self.maxCodeCache: int = cached_code_bytes
+ self.nodes: dict = in3_registry
+ if self.key:
+ warnings.warn('In3 Config: `account_secret` may cause instability.', DeprecationWarning)
+
+
+class ChainConfig:
+ """
+ Default in3 client configuration for each chain see #clientConfig for details.
+ """
+
+ def __init__(self, chain_id: int, chain_id_alias: str, client_config: ClientConfig):
+ self.chain_id: int = chain_id
+ self.chain_id_alias: str = chain_id_alias
+ self.client_config: ClientConfig = client_config
+
+
+chain_configs = {
+ "mainnet": ChainConfig(
+ chain_id=int(0x1),
+ chain_id_alias="mainnet",
+ client_config=ClientConfig(
+ chain_finality_threshold=10,
+ latest_block_stall=10,
+ node_signatures=2)
+ ),
+ "kovan": ChainConfig(
+ chain_id=int(0x2a),
+ chain_id_alias="kovan",
+ client_config=ClientConfig(
+ chain_finality_threshold=1,
+ latest_block_stall=6,
+ node_signatures=1,
+ node_signature_consensus=3)
+ ),
+ "evan": ChainConfig(
+ chain_id=int(0x4b1),
+ chain_id_alias="evan",
+ client_config=ClientConfig(
+ chain_finality_threshold=1,
+ latest_block_stall=6,
+ node_signatures=0,
+ node_signature_consensus=5)
+ ),
+ "goerli": ChainConfig(
+ chain_id=int(0x5),
+ chain_id_alias="goerli",
+ client_config=ClientConfig(
+ chain_finality_threshold=1,
+ latest_block_stall=6,
+ node_signatures=2)
+ ),
+ "ipfs": ChainConfig(
+ chain_id=int(0x7d0),
+ chain_id_alias="ipfs",
+ client_config=ClientConfig(
+ chain_finality_threshold=1,
+ latest_block_stall=5,
+ node_signatures=1,
+ node_signature_consensus=1
+ )
+ ),
+}
diff --git a/python/in3/transport.py b/python/in3/transport.py
new file mode 100644
index 000000000..9ee56cf94
--- /dev/null
+++ b/python/in3/transport.py
@@ -0,0 +1,67 @@
+import ctypes as c
+
+import requests
+
+from in3.libin3.lib_loader import libin3
+
+
+class In3Request(c.Structure):
+ """
+ Request sent by the libin3 to the In3 Network, transported over the _http_transport function
+ Based on in3/client/.h in3_request_t struct
+ Attributes:
+ payload (str): the payload to send
+ urls ([str]): array of urls
+ urls_len (int): number of urls
+ results (str): the responses
+ timeout (int): the timeout 0= no timeout
+ times (int): measured times (in ms) which will be used for ajusting the weights
+ """
+ _fields_ = [("payload", c.POINTER(c.c_char)),
+ ("urls", c.POINTER(c.POINTER(c.c_char))),
+ ("urls_len", c.c_int),
+ ("results", c.c_void_p),
+ ("timeout", c.c_uint32),
+ ("times", c.c_uint32)]
+
+
+def _transport_report_success(in3_request: In3Request, i: int, response: requests.Response):
+ libin3.in3_req_add_response(in3_request.results, i, False, response.content, len(response.content))
+
+
+def _transport_report_failure(in3_request: In3Request, i: int, msg: bytes):
+ libin3.in3_req_add_response(in3_request.results, i, True, msg, len(msg))
+
+
+@c.CFUNCTYPE(c.c_int, c.POINTER(In3Request))
+def http_transport(in3_request: In3Request):
+ """
+ Transports each request coming from libin3 to the in3 network and and reports the answer back
+ Args:
+ in3_request (In3Request): request sent by the In3 Client Core to the In3 Network
+ Returns:
+ exit_status (int): Always zero for signaling libin3 the function executed OK.
+ """
+ in3_request = in3_request.contents
+
+ for i in range(0, in3_request.urls_len):
+ try:
+ http_request = {
+ 'url': c.string_at(in3_request.urls[i]),
+ 'data': c.string_at(in3_request.payload),
+ 'headers': {'Content-type': 'application/json'},
+ 'timeout': in3_request.timeout
+ }
+ response = requests.post(**http_request)
+ response.raise_for_status()
+ if 'error' in response.text:
+ _transport_report_failure(in3_request, i, response.content)
+ else:
+ _transport_report_success(in3_request, i, response)
+ except requests.exceptions.RequestException as err:
+ _transport_report_failure(in3_request, i, str(err).encode('utf8'))
+ except requests.exceptions.SSLError as err:
+ _transport_report_failure(in3_request, i, str(err).encode('utf8'))
+ except Exception as err:
+ _transport_report_failure(in3_request, i, str(err).encode('utf8'))
+ return 0
diff --git a/python/in3/wallet.py b/python/in3/wallet.py
new file mode 100644
index 000000000..f506ed253
--- /dev/null
+++ b/python/in3/wallet.py
@@ -0,0 +1,86 @@
+import random
+
+from in3.eth.factory import EthObjectFactory
+from in3.eth.model import Account
+from in3.libin3.enum import In3Methods
+from in3.libin3.runtime import In3Runtime
+
+
+class WalletApi:
+ """
+ Ethereum accounts holder and manager.
+ """
+
+ def __init__(self, runtime: In3Runtime):
+ self._runtime = runtime
+ self._factory = EthObjectFactory(runtime)
+ # TODO: Persistence
+ self._accounts: dict = {}
+
+ def new_account(self, name: str, qrng=False) -> Account:
+ """
+ Creates a new Ethereum account and saves it in the wallet.
+ Args:
+ name (str): Account identifier to use with `get`. i.e. get('my_wallet`)
+ qrng (bool): True uses a quantum random number generator api for generating the private key.
+ Returns:
+ account (Account): Newly created Ethereum account.
+ """
+ if qrng:
+ raise NotImplementedError
+ secret = hex(random.getrandbits(256))
+ return self._create_account(name, secret)
+
+ def get(self, name: str) -> Account or None:
+ """
+ Returns account in case it exists. Doesnt fail for easier handling w/out try catch. i.e: if get('my_wallet'): do
+ Args:
+ name (str): Account identifier to use with `get`. i.e. get('my_wallet`)
+ Returns:
+ account (Account): Selected Ethereum account.
+ """
+ if name not in self._accounts.keys():
+ return None
+ return self._accounts[name]
+
+ def delete(self, name: str) -> bool:
+ """
+ Deletes an account in case it exists.
+ Args:
+ name (str): Account identifier.
+ Returns:
+ success (bool): True if account exists and was deleted.
+ """
+ if name not in self._accounts.keys():
+ return False
+ del self._accounts[name]
+ return True
+
+ def recover_account(self, name: str, secret: str) -> Account:
+ """
+ Recovers an account from a secret.
+ Args:
+ name (str): Account identifier to use with `get`. i.e. get('my_wallet`)
+ secret (str): Account private key in hexadecimal string
+ Returns:
+ account (Account): Recovered Ethereum account.
+ """
+ return self._create_account(name, secret)
+
+ def parse_mnemonics(self, mnemonics: str) -> str:
+ """
+ Recovers an account secret from mnemonics phrase
+ Args:
+ mnemonics (str): BIP39 mnemonics phrase.
+ Returns:
+ secret (str): Account secret. Use `recover_account` to create a new account with this secret.
+ """
+ raise NotImplementedError
+
+ def _create_account(self, name: str, secret: str) -> Account:
+ if not secret.startswith('0x') or not len(secret) == 66:
+ TypeError('Secret must be a 256 bit hexadecimal.')
+ address = self._runtime.call(In3Methods.PK_2_ADDRESS, secret)
+ account = self._factory.get_account(address, int(secret, 16))
+ self._accounts[name] = account
+ return account
diff --git a/python/publish.sh b/python/publish.sh
index 7cfcfdf60..6e224d132 100755
--- a/python/publish.sh
+++ b/python/publish.sh
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
rm -rf dist
-
+cp ../LICENSE ../LICENSE.AGPL ./
python3 setup.py sdist
+rm LICENSE LICENSE.AGPL
-twine upload --verbose --repository-url https://upload.pypi.org/legacy/ -u __token__ -p $PIP_TOKEN dist/*
+twine upload --verbose --repository-url https://upload.pypi.org/legacy/ -u __token__ -p "$PIP_TOKEN" dist/*
#pip3 install twine
diff --git a/python/requirements.txt b/python/requirements.txt
index ebd8e7a36..dce680f3c 100644
--- a/python/requirements.txt
+++ b/python/requirements.txt
@@ -1,14 +1,17 @@
astroid==2.3.3
attrs==19.3.0
+bleach==3.1.5
certifi==2019.11.28
chardet==3.0.4
click==7.1.1
+docutils==0.16
future==0.18.2
idna==2.9
importlib-metadata==1.6.0
isort==4.3.21
Jinja2==2.11.1
junit-xml==1.9
+keyring==21.2.1
lazy-object-proxy==1.4.3
livereload==2.6.1
lunr==0.5.6
@@ -19,24 +22,31 @@ mkdocs==1.1
more-itertools==8.2.0
nltk==3.4.5
packaging==20.3
+pkginfo==1.5.0.1
pluggy==0.13.1
py==1.8.1
pycodestyle==2.5.0
pydoc-markdown==2.1.3
pydocstyle==5.0.2
pyflakes==2.1.1
+Pygments==2.6.1
pylama==7.7.1
pylint==2.4.4
pyparsing==2.4.7
pytest==5.4.1
PyYAML==5.3.1
+readme-renderer==26.0
requests==2.23.0
+requests-toolbelt==0.9.1
six==1.14.0
snowballstemmer==2.0.0
tornado==6.0.4
+tqdm==4.46.0
+twine==3.1.1
typed-ast==1.4.1
urllib3==1.25.8
wcwidth==0.1.9
+webencodings==0.5.1
wrapt==1.11.2
yapf==0.29.0
zipp==3.1.0
diff --git a/python/setup.py b/python/setup.py
index 22be73267..95dda71ee 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -1,6 +1,6 @@
import pathlib
import setuptools
-import os
+from os import environ
"""
Information on how to build this file
@@ -8,17 +8,18 @@
https://pypi.org/classifiers/
"""
-envs = os.environ
-version = envs.get("version", "0.0.15")
-url = envs.get("url", "https://github.com/slockit/in3-c")
-download_url = envs.get("download_url","https://git.slock.it/in3/c/in3-python/-/archive/dev_0.1.0/in3-python-dev_0.1.0.tar.gz")
-license = envs.get("license", "LGPL")
-description = envs.get("description", "Incubed client and provider for web3. Based on in3-c for cython runtime.")
-keywords = envs.get("keywords", "in3").split(",")
+
+version = environ.get("version", "2.3.0")
+url = environ.get("url", "https://github.com/slockit/in3-c")
+License = environ.get("license", "AGPL")
+description = environ.get(
+ "description", "Incubed client and provider for web3. Based on in3-c runtime.")
+keywords = environ.get(
+ "keywords", "in3,c,arm,x86,x64,macos,windows,linux,blockchain,ethereum,bitcoin,ipfs").split(",")
readme = (pathlib.Path(__file__).parent / "README.md").read_text()
-name = envs.get("name", "in3")
-author = envs.get("author", "github.com/slockit")
-author_email = envs.get("author_email", "products@slock.it")
+name = environ.get("name", "in3")
+author = environ.get("author", "github.com/slockit/in3-c")
+author_email = environ.get("author_email", "products@slock.it")
setuptools.setup(
name=name,
version=version,
@@ -29,16 +30,16 @@
long_description_content_type="text/markdown",
url=url,
packages=setuptools.find_packages(exclude=["docs", "tests"]),
- install_requires=['requests=>2.23.0'],
+ install_requires=['requests==2.23.0'],
keywords=keywords,
+ include_package_data=True,
classifiers=[
"Programming Language :: Python :: 3",
- "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
+ "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
"Operating System :: OS Independent",
"Natural Language :: English",
"Intended Audience :: Science/Research",
"Environment :: Console",
- "Development Status :: 2 - Pre-Alpha"
- ],
+ "Development Status :: 4 - Beta"
+ ]
)
-
diff --git a/python/tests/__init__.py b/python/tests/__init__.py
index e69de29bb..e311f8d33 100644
--- a/python/tests/__init__.py
+++ b/python/tests/__init__.py
@@ -0,0 +1,5 @@
+"""
+Tests module
+
+Contains test transport, test client configuration and mocked network responses.
+"""
diff --git a/python/tests/integrated/__init__.py b/python/tests/integrated/__init__.py
index e69de29bb..fccf83e18 100644
--- a/python/tests/integrated/__init__.py
+++ b/python/tests/integrated/__init__.py
@@ -0,0 +1,8 @@
+"""
+Integrated tests for `in3`
+
+Tests data marshalling from and to libin3.
+Tests minimum, happy path, client consistency and stability.
+Calls all implemented calls from Python to libin3.
+Uses real network data mocked locally.
+"""
diff --git a/python/tests/integrated/client_test.py b/python/tests/integrated/client_test.py
new file mode 100644
index 000000000..e721fc918
--- /dev/null
+++ b/python/tests/integrated/client_test.py
@@ -0,0 +1,75 @@
+"""
+Integrated tests for `in3` module. Doesnt test submodules.
+"""
+import unittest
+
+import in3
+from tests.mock.config import mock_config
+from tests.transport import mock_transport
+
+
+class MainNetClientTest(unittest.TestCase):
+
+ def setUp(self):
+ # self.client = in3.Client(in3_config=mock_config)
+ self.client = in3.Client(in3_config=mock_config, transport=mock_transport)
+
+ def test_configure(self):
+ client = in3.Client()
+ self.assertIsInstance(client, in3.Client)
+ client = in3.Client(in3_config=in3.model.ClientConfig())
+ self.assertIsInstance(client, in3.Client)
+
+ def test_node_list(self):
+ node_list = self.client.refresh_node_list()
+ self.assertIsInstance(node_list, in3.model.NodeList)
+
+ def test_ens_resolve(self):
+ # Other calls like `addr` require more than one eth_call, being more complex to mock the tests. Suffice for now.
+ with self.assertRaises(in3.EthAddressFormatException):
+ self.client.ens_owner('depraz.eth', 'asd')
+ address = self.client.ens_owner('depraz.eth')
+ self.assertEqual(address, '0x0b56ae81586d2728ceaf7c00a6020c5d63f02308')
+
+ def test_ens_namehash(self):
+ foo_name = self.client.ens_namehash('foo.eth')
+ self.assertEqual(foo_name, '0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f')
+
+
+class KovanClientTest(MainNetClientTest):
+
+ def setUp(self):
+ # self.client = in3.Client('kovan', in3_config=mock_config)
+ self.client = in3.Client('kovan', in3_config=mock_config, transport=mock_transport)
+
+ def test_configure(self):
+ client = in3.Client('kovan')
+ self.assertIsInstance(client, in3.Client)
+ client = in3.Client('kovan', in3.model.ClientConfig())
+ self.assertIsInstance(client, in3.Client)
+
+ def test_ens_resolve(self):
+ # Not supported by app.ens.domains!
+ return
+
+
+class GoerliClientTest(MainNetClientTest):
+
+ def setUp(self):
+ # self.client = in3.Client('goerli', in3_config=mock_config)
+ self.client = in3.Client('goerli', in3_config=mock_config, transport=mock_transport)
+
+ def test_configure(self):
+ client = in3.Client('goerli')
+ self.assertIsInstance(client, in3.Client)
+ client = in3.Client('goerli', in3.model.ClientConfig())
+ self.assertIsInstance(client, in3.Client)
+
+ def test_ens_resolve(self):
+ # Other calls like `addr` require more than one eth_call, being more complex to mock the tests. Suffice for now.
+ address = self.client.ens_owner('depraz.eth')
+ self.assertEqual(address, '0x0b56ae81586d2728ceaf7c00a6020c5d63f02308')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/integrated/eth_account_test.py b/python/tests/integrated/eth_account_test.py
index 2c5c4ac5c..3d9f06109 100644
--- a/python/tests/integrated/eth_account_test.py
+++ b/python/tests/integrated/eth_account_test.py
@@ -1,11 +1,18 @@
+"""
+Integrated tests for `in3.eth.account` module.
+"""
import unittest
+
import in3
+from tests.mock.config import mock_config
+from tests.transport import mock_transport
-class UtilsTestCase(unittest.TestCase):
+class EthAccountGoerliTestCase(unittest.TestCase):
def setUp(self):
- self.client = in3.Client()
+ # self.client = in3.Client('goerli', in3_config=mock_config)
+ self.client = in3.Client('goerli', in3_config=mock_config, transport=mock_transport)
def test_checksum_address(self):
missing_0x_address = '1fe2e9bf29AA1938859aF64C413361227d04059A'
@@ -18,7 +25,7 @@ def test_checksum_address(self):
address_false = self.client.eth.account.checksum_address(mixed_case_address, False)
self.assertEqual(address_false, '0x1Fe2E9bf29aa1938859Af64C413361227d04059a')
address_true = self.client.eth.account.checksum_address(mixed_case_address)
- self.assertEqual(address_true, '0x1fe2e9Bf29aA1938859AF64C413361227d04059a')
+ self.assertNotEqual(address_true, '0x1Fe2E9bf29aa1938859Af64C413361227d04059a')
# Check lower
self.assertEqual(self.client.eth.account.checksum_address(mixed_case_address.lower()), address_true)
self.assertEqual(self.client.eth.account.checksum_address(mixed_case_address.lower(), False), address_false)
@@ -27,6 +34,101 @@ def test_checksum_address(self):
self.assertEqual(address_false, self.client.eth.account.checksum_address(address_true, False))
def test_sign(self):
- # TODO: Check sign mock data
- result = self.client.eth.account.sign('0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad', "test 123")
- self.assertEqual(result, "asd")
+ message = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
+ private_key = '0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8'
+ singature = self.client.eth.account.sign(private_key, message)
+ self.assertEqual(singature,
+ "0xdd34194276b13f44d3f83401f87da6672dd8dc5905590b7ef44623f424af462f70ce23d37b4" +
+ "ada4ff33f5645df62524402c4fb5cac5dca3bce60331f8d6bc5d41c")
+
+ def test_estimate_gas(self):
+ transaction = in3.eth.NewTransaction(
+ From="0x132D2A325b8d588cFB9C1188daDdD4d00193E028",
+ to="0xF5FEb05CA1b451d60b343f5Ee12df2Cc4ce2691B",
+ nonce=5,
+ data="0x9a5c90aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000002386f26fc1000000000000000000000000000015094fc63f03e46fa211eb5708088dda62" +
+ "782dc4000000000000000000000000000000000000000000000004563918244f400000")
+ gas = self.client.eth.account.estimate_gas(transaction)
+ self.assertGreater(gas, 1000)
+
+ def test_get_transaction_count(self):
+ rpc = self.client.eth.account.transaction_count('0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308')
+ self.assertGreaterEqual(rpc, 0)
+
+ def test_get_balance(self):
+ result = self.client.eth.account.balance('0x6FA33809667A99A805b610C49EE2042863b1bb83')
+ self.assertGreaterEqual(result, 0)
+
+ def test_send_tx(self):
+ # 1000000000000000000 == 1 ETH
+ # SK to PK 0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308
+ secret = hex(0x9852782BEAD36C64161665586D33391ECEC1CCED7432A1D66FD326D38EA0171F)
+ sender = self.client.eth.account.recover(secret)
+ receiver = hex(0x6FA33809667A99A805b610C49EE2042863b1bb83)
+ tx = in3.eth.NewTransaction(to=receiver, value=1463926659)
+ tx_hash = self.client.eth.account.send_transaction(sender, tx)
+ self.assertEqual(tx_hash, '0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd')
+
+ def test_send_raw_transaction(self):
+ raw_tx = "0xf867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de" + \
+ "57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d1393" + \
+ "03576956ca5aaefc7ac3"
+ tx_hash = self.client.eth.account.send_raw_transaction(raw_tx)
+ self.assertEqual(tx_hash, "0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd")
+
+
+class EthAccountKovanTestCase(EthAccountGoerliTestCase):
+
+ def setUp(self):
+ # self.client = in3.Client('kovan', in3_config=mock_config)
+ self.client = in3.Client('kovan', in3_config=mock_config, transport=mock_transport)
+
+ def test_get_transaction_count(self):
+ rpc = self.client.eth.account.transaction_count('0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308')
+ self.assertGreaterEqual(rpc, 0)
+
+ def test_send_tx(self):
+ # 1000000000000000000 == 1 ETH
+ # SK to PK 0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308
+ secret = hex(0x9852782BEAD36C64161665586D33391ECEC1CCED7432A1D66FD326D38EA0171F)
+ sender = self.client.eth.account.recover(secret)
+ receiver = hex(0x6FA33809667A99A805b610C49EE2042863b1bb83)
+ tx = in3.eth.NewTransaction(to=receiver, value=1463926659)
+ tx_hash = self.client.eth.account.send_transaction(sender, tx)
+ self.assertEqual(tx_hash, '0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4')
+
+ def test_send_raw_transaction(self):
+ raw_tx = "0xf86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e173" + \
+ "06d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd36413" + \
+ "26089fb43569820a7b6d"
+ tx_hash = self.client.eth.account.send_raw_transaction(raw_tx)
+ self.assertEqual(tx_hash, "0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4")
+
+
+class EthAccountTestCase(EthAccountGoerliTestCase):
+
+ def setUp(self):
+ # self.client = in3.Client(in3_config=mock_config)
+ self.client = in3.Client(in3_config=mock_config, transport=mock_transport)
+
+ def test_get_transaction_count(self):
+ rpc = self.client.eth.account.transaction_count('0x6FA33809667A99A805b610C49EE2042863b1bb83')
+ self.assertGreater(rpc, 0)
+
+ def test_send_tx(self):
+ # 1000000000000000000 == 1 ETH
+ # SK to PK 0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308
+ secret = hex(0xAC6D6BF94AD0AC65869EF6A0A47A9F2A201956D4AF3FFBE9DFE679399DACD3D9)
+ sender = self.client.eth.account.recover(secret)
+ receiver = hex(0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308)
+ tx = in3.eth.NewTransaction(to=receiver, value=1463926659)
+ tx_hash = self.client.eth.account.send_transaction(sender, tx)
+ self.assertEqual(tx_hash, '0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc')
+
+ def test_send_raw_transaction(self):
+ raw_tx = "0xf868098502540be400825208940b56ae81586d2728ceaf7c00a6020c5d63f02308845741bf838026a070af62c71480" + \
+ "8c7607ebe2cc756f20bed9790e5f5f20b192a83f689157a44bd0a0768a5d94766f1645e652dbef3826eed94074b5481a" + \
+ "453ad12aa52ae6f8e42606"
+ tx_hash = self.client.eth.account.send_raw_transaction(raw_tx)
+ self.assertEqual(tx_hash, "0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc")
diff --git a/python/tests/integrated/eth_api_test.py b/python/tests/integrated/eth_api_test.py
index 3cfa7c5d2..1257da35a 100644
--- a/python/tests/integrated/eth_api_test.py
+++ b/python/tests/integrated/eth_api_test.py
@@ -1,12 +1,18 @@
+"""
+Integrated tests for `in3.eth` module.
+"""
import unittest
+
import in3
+from tests.mock.config import mock_config
+from tests.transport import mock_transport
class EthereumTest(unittest.TestCase):
def setUp(self):
- conf = in3.model.ClientConfig(signatureCount=1, chainId=str(in3.Chain.MAINNET))
- self.client = in3.Client(in3_config=conf)
+ # self.client = in3.Client(in3_config=mock_config)
+ self.client = in3.Client(in3_config=mock_config, transport=mock_transport)
def test_ethereum_sha3(self):
digest = self.client.eth.keccak256('0x68656c6c6f20776f726c64')
@@ -17,253 +23,73 @@ def test_eth_gasPrice(self):
def test_block_number(self):
result = self.client.eth.block_number()
- self.assertGreater(result, 15344774)
-
- def test_get_balance(self):
- result = self.client.eth.get_balance("0x16d4aBf4F640CBA3768A3B75F1bB060B0cC77194")
- self.assertGreaterEqual(result, 0)
- result = self.client.eth.get_balance("0x16d4aBf4F640CBA3768A3B75F1bB060B0cC77194", 15344774)
- self.assertGreaterEqual(result, 0)
- result = self.client.eth.get_balance("0x16d4aBf4F640CBA3768A3B75F1bB060B0cC77194", 'earliest')
- self.assertGreaterEqual(result, 0)
-
- def test_get_storage_at(self):
- rpc = self.client.eth.get_storage_at(
- address=in3.eth.Address("0xaF91fF3c7E46D40684703F514783FA8880FF8C57", skip_validation=True), position=0,
- at_block=in3.BlockStatus.LATEST)
- self.assertEqual(rpc, '0x000000000000000000000000b31097ef4bd61b6aa1135c27cd475635298ac8ec')
-
- def test_get_transaction_count(self):
- address = in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- rpc = self.client.eth.get_transaction_count(address=address, at_block=in3.BlockStatus.LATEST)
- self.assertGreater(rpc, 60)
-
- # TODO: Fix Error
- # in3.model.exception.In3RequestException: {'code': -4, 'message': '[0x1]:The Method cannot be verified with eth_nano!'}
- # this means C in3 is configured as nano...
- def test_get_block_transaction_count_by_hash(self):
- hash_obj = in3.eth.Hash("0x97786c76ed653d36bb8a0d10563fe5814febbdff946316d4f4e8f6f3bb0f77e8")
- rpc = self.client.eth.get_block_transaction_count_by_hash(block_hash=hash_obj)
- self.assertGreaterEqual(rpc, 0)
-
- # TODO: STOPPED HERE
- # TODO: ERROR
- # in3.model.exception.In3RequestException: {'code': -4, 'message': '[0x1]:The Method cannot be verified with eth_nano!'}
- def test_get_block_transaction_count_by_number(self):
- number = int("0xd12321", 16)
- rpc = self.client.eth.get_block_transaction_count_by_number(number=number)
- self.assertGreaterEqual(rpc, 0)
-
- # removed
- # def test_get_uncle_count_by_block_hash(self):
- # hash_obj = in3.eth.Hash("0x97786c76ed653d36bb8a0d10563fe5814febbdff946316d4f4e8f6f3bb0f77e8")
- # rpc = self.client.eth.get_uncle_count_by_block_hash(block_hash=hash_obj)
- # self.assertGreaterEqual(rpc, 0)
-
- # removed
- # def test_get_uncle_count_by_block_number(self):
- # number = 14891999
- # rpc = self.client.eth.get_uncle_count_by_block_number(number=number)
- # self.assertGreaterEqual(rpc, 0)
-
- def test_get_code(self):
- address = in3.eth.Address("0xe323f6a06AbFe88B82f8a1cc8B0b9d55D253cCBf")
- result = self.client.eth.get_code(address=address, at_block=in3.BlockStatus.LATEST)
- self.assertEqual(result,
- "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80638c65c81f116100f9578063c05aff5c11610097578063d924393e11610071578063d924393e14610536578063dfefddde1461053e578063f14fcbc814610546578063f897a22b14610563576101a9565b8063c05aff5c146104eb578063c2ca0ac514610511578063c8bc58d91461052e576101a9565b806392166aa4116100d357806392166aa41461047b57806399cdfd4d14610483578063a35bb3a91461048b578063a426e4c814610493576101a9565b80638c65c81f146103f95780638cd221c91461046b5780638da5cb5b14610473576101a9565b80635b28af6d116101665780636d0bf58d116101405780636d0bf58d1461036f578063745921eb14610377578063765339461461039b57806389fb2682146103cd576101a9565b80635b28af6d146102ef5780635b410881146102f75780635eac6239146102ff576101a9565b8063200d2ed2146101ab57806322508e5d146101d75780633501f777146101f45780633b0c3a7c1461020e578063429b62e5146102875780634b0bddd2146102c1575b005b6101b361056b565b604051808260028111156101c357fe5b60ff16815260200191505060405180910390f35b6101a9600480360360208110156101ed57600080fd5b503561057b565b6101fc610b69565b60408051918252519081900360200190f35b6101a96004803603604081101561022457600080fd5b81019060208101813564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184602083028401116401000000008311171561027357600080fd5b9193509150356001600160a01b0316610b6f565b6102ad6004803603602081101561029d57600080fd5b50356001600160a01b0316610e43565b604080519115158252519081900360200190f35b6101a9600480360360408110156102d757600080fd5b506001600160a01b0381351690602001351515610e58565b6101fc610ed4565b6102ad610eda565b6101a96004803603602081101561031557600080fd5b81019060208101813564010000000081111561033057600080fd5b82018360208201111561034257600080fd5b8035906020019184602083028401116401000000008311171561036457600080fd5b509092509050610eea565b6101fc611502565b61037f611508565b604080516001600160a01b039092168252519081900360200190f35b6101a9600480360360608110156103b157600080fd5b50803590602081013590604001356001600160a01b0316611517565b6101fc600480360360408110156103e357600080fd5b50803590602001356001600160a01b0316611a84565b6104166004803603602081101561040f57600080fd5b5035611ab1565b6040805198895260208901979097528787019590955260608701939093526001600160801b0391821660808701521660a085015266ffffffffffffff1660c0840152151560e083015251908190036101000190f35b6101fc611b10565b61037f611b16565b6101a9611b25565b6101fc611c10565b6101a9611c94565b6104b6600480360360408110156104a957600080fd5b5080359060200135611db0565b6040805195151586526001600160a01b0390941660208601528484019290925260608401526080830152519081900360a00190f35b6101a96004803603602081101561050157600080fd5b50356001600160a01b0316611e81565b6101a96004803603602081101561052757600080fd5b5035611fc2565b6101a96123bd565b6101a96124b9565b6101fc612702565b6101a96004803603602081101561055c57600080fd5b5035612708565b61037f61284a565b601154600160a01b900460ff1681565b6002601154600160a01b900460ff16600281111561059557fe5b146105de5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b600b54600019016105ed6135f4565b506000818152600a6020908152604091829020825161010081018452815481526001820154928101929092526002810154928201929092526003820154606082015260048201546001600160801b0380821660808401819052600160801b9092041660a083015260059092015466ffffffffffffff811660c0830152600160381b900460ff16151560e0820152906106e65760118054600160a01b60ff0219169055610e104201600f5560c08101516040805184815266ffffffffffffff909216602083015280517f34fa627446f032cedc60a5521c4a8fbdd28f3ce106d8c6f6c17322ada873cebb9281900390910190a15050610b66565b60a081015160808201516001600160801b0391821685019116811115610716575060808101516001600160801b03165b61071e613656565b61072b8360600151612859565b9050610735613675565b61074b8460c0015166ffffffffffffff16612906565b60a08501519091506000906001016001600160801b03165b848111610913576000878152600a60209081526040808320848452600701909152902054600160a81b900466ffffffffffffff168061087b576107a4613656565b6000898152600a60209081526040808320868452600801909152902080546001909101546107d391908761296a565b905060005b600a8110156108745760008282600a81106107ef57fe5b60200201519050801561086b57808883600a811061080957fe5b602002018051909101905260019550600282101561086b57604080518c81526020810187905260018401818301526060810183905290517fed3e993150009d92ad8e13c907a93c9cee21fa0f33be6bb017ef7d0b54eb44b99181900360800190a15b506001016107d8565b505061090a565b60006108908266ffffffffffffff1686612af9565b90508015610908578560018203600a81106108a757fe5b60200201805160019081019091529350600381101561090857604080518a8152602081018590528082018390526001606082015290517fed3e993150009d92ad8e13c907a93c9cee21fa0f33be6bb017ef7d0b54eb44b99181900360800190a15b505b50600101610763565b506001600160801b0380851660a0870181905260808701519091161415610b0e576000805b6008811015610972576002816008811061094e57fe5b01548582600201600a811061095f57fe5b6020020151029190910190600101610938565b508061097c611c10565b10156109ca5760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600c54818110156109dc5760006109e0565b8181035b855160208701519192506127106114dc84028190049261029485029190910491908115610a1657818481610a1057fe5b04610a19565b60005b60208c01528015610a3357808381610a2d57fe5b04610a36565b60005b60408c0181905260208c015183029082028701018015610a5957600d8054820190555b60208c015115610a7d576020808d015160008f8152600a9092526040909120600101555b60408c015115610aa0576040808d015160008f8152600a60205291909120600201555b60118054600160a01b60ff0219169055610e10420163ffffffff16600f5560c08c0151604080518f815266ffffffffffffff909216602083015280517f34fa627446f032cedc60a5521c4a8fbdd28f3ce106d8c6f6c17322ada873cebb9281900390910190a1505050505050505b8015610b3057610b1d83612cb4565b6000878152600a60205260409020600301555b5050505060a001516000918252600a602052604090912060040180546001600160801b03928316600160801b0292169190911790555b50565b600e5481565b60115460408051600160e01b6323b872dd028152336004820152306024820152622dc6c0850260448201819052915185936001600160a01b0316916323b872dd9160648083019260209291908290030181600087803b158015610bd157600080fd5b505af1158015610be5573d6000803e3d6000fd5b505050506040513d6020811015610bfb57600080fd5b5051610c3b57604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60006001600160a01b0384163314610c535783610c56565b60005b600b546000818152600a602052604081206004015492935090916001600160801b0316905b85811015610d8c576000898983818110610c9157fe5b905060200201359050610ca381612d38565b6040805160608082018352600080835233602080850182815266ffffffffffffff8881168789019081528c8652600a845288862060019c909c016001600160801b0381168088526007909d01855295899020975188549351915160ff1990941690151517610100600160a81b0319166101006001600160a01b039283160217600160a81b600160e01b031916600160a81b93909216929092021790955585518a815290810198909852928916878501529251929591927ff152feb5fe7641aae5c7f8e8187c26eef1a9d970f7c3794ac442f0842282d93f9281900390910190a250600101610c7b565b506000828152600a6020526040902060040180546001600160801b0319166001600160801b0383161790556010546001600160a01b03166360b0b0f0612710610bb8870204856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b158015610e2157600080fd5b505af1158015610e35573d6000803e3d6000fd5b505050505050505050505050565b60016020526000908152604090205460ff1681565b6000546001600160a01b03163314610ea95760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1037bbb732b902604482015290519081900360640190fd5b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b600f5481565b601154600160a81b900460ff1681565b60028106158015610efc575060028110155b610f505760408051600160e51b62461bcd02815260206004820152600e60248201527f696e76616c6964206c656e677468000000000000000000000000000000000000604482015290519081900360640190fd5b600082826000818110610f5f57fe5b602090810292909201356000818152600a90935260409092206004015491925050600160801b81046001600160801b03908116911614610fdd5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000818152600a6020526040812081906007018186866001818110610ffe57fe5b90506020020135815260200190815260200160002060000160019054906101000a90046001600160a01b03169050611034613675565b6000848152600a60205260409020600501546110589066ffffffffffffff16612906565b905060005b858110156113d35786868281811061107157fe5b90506020020135851461112f5786868281811061108a57fe5b602090810292909201356000818152600a90935260409092206004015491965050600160801b81046001600160801b039081169116146111085760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000858152600a602052604090206005015461112c9066ffffffffffffff16612906565b91505b600087878360010181811061114057fe5b9050602002013590506111516136b2565b506000868152600a602090815260408083208484526007018252918290208251606081018452905460ff8116151580835261010082046001600160a01b031693830193909352600160a81b900466ffffffffffffff1692810192909252806111c4575060208101516001600160a01b0316155b806111e5575080602001516001600160a01b0316856001600160a01b031614155b156111f15750506113cb565b6000816040015166ffffffffffffff16600014156112e057611211613656565b6000898152600a602090815260408083208784526008019091529020805460019091015461124091908861296a565b905060015b600a81116112d95760008260018303600a811061125e57fe5b6020020151905080156112d05781600114156112905760008b8152600a602052604090206001015493909301926112d0565b81600214156112b75760008b8152600a6020526040902060020154810293909301926112d0565b80600260038403600881106112c857fe5b015402840193505b50600101611245565b505061135c565b60006112f9836040015166ffffffffffffff1687612af9565b9050806001141561131d576000898152600a6020526040902060010154915061135a565b806002141561133f576000898152600a6020526040902060020154915061135a565b801561135a576002600382036008811061135557fe5b015491505b505b80156113c7576000888152600a60209081526040808320868452600701825291829020805460ff1916600117905581518a81529081018590528151988301987f179780be10c742bdbc92cd0af59e83edeb067cd1954ef4d647827d8504c7c2ca929181900390910190a15b5050505b60020161105d565b506000831161141a5760408051600160e51b62461bcd0281526020600482015260086024820152600160c01b676e6f207072697a6502604482015290519081900360640190fd5b82600d54101561146c5760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600d8054849003905560115460408051600160e01b63a9059cbb0281526001600160a01b038581166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156114ce57600080fd5b505af11580156114e2573d6000803e3d6000fd5b505050506040513d60208110156114f857600080fd5b5050505050505050565b600d5481565b6010546001600160a01b031681565b60f883901c60ff60f085901c1660068210801590611536575060268211155b61158a5760408051600160e51b62461bcd02815260206004820152601260248201527f696e76616c6964207a6f6e6531436f756e740000000000000000000000000000604482015290519081900360640190fd5b6001811015801561159c575060088111155b6115f05760408051600160e51b62461bcd02815260206004820152601260248201527f696e76616c6964207a6f6e6532436f756e740000000000000000000000000000604482015290519081900360640190fd5b6000816115fe846006612fa7565b60115460408051600160e01b6323b872dd02815233600482015230602482015292909302622dc6c081026044840181905293519094506001600160a01b03909116916323b872dd9160648083019260209291908290030181600087803b15801561166757600080fd5b505af115801561167b573d6000803e3d6000fd5b505050506040513d602081101561169157600080fd5b50516116d157604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60ff60e888901c1660018110156117205760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b6002840160031b611734898360188461303f565b9150600882111561177d5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b8060f80389901c60ff16915060018210156117d05760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b600385601e0387116117e7578587016002016117ea565b60205b901b90506118018983600388600301901b8461303f565b915084601e0386111561183057600385601e880301901b905061182d8883600388600301901b8461303f565b91505b60268211156118775760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b60006001600160a01b038816331461188f5787611892565b60005b600b546000818152600a60209081526040808320600481015482516060810184528581523381860190815281850187815260016001600160801b03948516019384168852600785018752858820925183549251915160ff1990931690151517610100600160a81b0319166101006001600160a01b039092169190910217600160a81b600160e01b031916600160a81b66ffffffffffffff9092169190910217905560089091019092529091208d9055919250908a15611977576000828152600a602090815260408083206001600160801b038516845260080190915290206001018b90555b604080518381526001600160801b03831660208201526001600160a01b03851681830152905133917ff152feb5fe7641aae5c7f8e8187c26eef1a9d970f7c3794ac442f0842282d93f919081900360600190a26000828152600a6020526040902060040180546001600160801b0319166001600160801b0383161790556010546001600160a01b03166360b0b0f0612710610bb8890204856040518363ffffffff1660e01b815260040180838152602001826001600160a01b03166001600160a01b0316815260200192505050600060405180830381600087803b158015611a5e57600080fd5b505af1158015611a72573d6000803e3d6000fd5b50505050505050505050505050505050565b6000828152600a602090815260408083206001600160a01b03851684526006019091529020545b92915050565b600a6020526000908152604090208054600182015460028301546003840154600485015460059095015493949293919290916001600160801b0380831692600160801b9004169066ffffffffffffff811690600160381b900460ff1688565b600b5481565b6000546001600160a01b031681565b6010546001600160a01b0316611b855760408051600160e51b62461bcd02815260206004820152601260248201527f66756e646572506f6f6c206e6f74207365740000000000000000000000000000604482015290519081900360640190fd5b60115460105460408051600160e01b63095ea7b30281526001600160a01b03928316600482015260001960248201529051919092169163095ea7b39160448083019260209291908290030181600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b505050506040513d6020811015611c0c57600080fd5b5050565b600d5460115460408051600160e01b6370a082310281523060048201529051600093926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c6257600080fd5b505afa158015611c76573d6000803e3d6000fd5b505050506040513d6020811015611c8c57600080fd5b505103905090565b601154600090600160a81b900460ff16611cb457600e54611c5c01611cbb565b603c600e54015b9050804211611d065760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b600b54600019016000908152600a6020526040902054611d25906130b0565b601154600160a81b900460ff16610b665760118054600160a81b60ff021916600160a81b17905560105460408051600160e11b63419ab82902815290516001600160a01b039092169163833570529160048082019260009290919082900301818387803b158015611d9557600080fd5b505af1158015611da9573d6000803e3d6000fd5b5050505050565b6000806000806000611dc06136b2565b506000878152600a602090815260408083208984526007018252918290208251606081018452905460ff81161515825261010081046001600160a01b031692820192909252600160a81b90910466ffffffffffffff1691810191909152611e256136d2565b506000978852600a60209081526040808a20988a526008909801815297879020875180890189528154808252600190920154908a0181905282519983015192909801519899919866ffffffffffffff1697909650945092505050565b6000546001600160a01b03163314611ed25760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1037bbb732b902604482015290519081900360640190fd5b6010546001600160a01b031615611f245760408051600160e51b62461bcd02815260206004820152600b6024820152600160aa1b6a185b1c9958591e481cd95d02604482015290519081900360640190fd5b601080546001600160a01b0319166001600160a01b0383811691821790925560115460408051600160e01b63095ea7b3028152600481019390935260001960248401525192169163095ea7b3916044808201926020929091908290030181600087803b158015611f9357600080fd5b505af1158015611fa7573d6000803e3d6000fd5b505050506040513d6020811015611fbd57600080fd5b505050565b6001601154600160a01b900460ff166002811115611fdc57fe5b146120255760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b600b54600019016120353361318b565b801561204b5750601154600160a81b900460ff16155b1561219157603c600e5401421161209e5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b6000818152600a602090815260408083208380526006019091529020546120c4836131c2565b1461210d5760408051600160e51b62461bcd02815260206004820152600e6024820152600160921b6d1a5b9d985b1a59081cd958dc995d02604482015290519081900360640190fd5b6000818152600a60208181526040808420848052600681018352908420849055928490525254820161213e816130b0565b6000828152600a6020908152604080832084905580518581529182019290925281517f18e3a2a1539c4d2325524f2c652bd26fea78b54a5861212876952caf2e00582b929181900390910190a1506122b4565b600e544211156121dd5760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b6000818152600a60209081526040808320338452600601909152902054612203836131c2565b1461224c5760408051600160e51b62461bcd02815260206004820152600e6024820152600160921b6d1a5b9d985b1a59081cd958dc995d02604482015290519081900360640190fd5b6000818152600a6020818152604080842033808652600682018452828620869055948690529282528254860190925581518481529081019290925280517f18e3a2a1539c4d2325524f2c652bd26fea78b54a5861212876952caf2e00582b9281900390910190a15b6000818152600a6020526040902060050154600160381b900460ff16611c0c576000818152600a60209081526040808320600501805467ff000000000000001916600160381b1790556011548151600160e01b63a9059cbb0281523360048201526305f5e100602482015291516001600160a01b039091169363a9059cbb93604480850194919392918390030190829087803b15801561235357600080fd5b505af1158015612367573d6000803e3d6000fd5b505050506040513d602081101561237d57600080fd5b50506040805182815233602082015281517fc7ad212fc37b0fda8af53154f4fc8674770b9d813b1863178c39c4ed2128edc1929181900390910190a15050565b601154600160a81b900460ff166123da57611c20600f54016123de565b600f545b42116124265760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b61242e6131e6565b601154600160a81b900460ff166124b75760118054600160a81b60ff021916600160a81b17905560105460408051600160e11b63419ab82902815290516001600160a01b039092169163833570529160048082019260009290919082900301818387803b15801561249e57600080fd5b505af11580156124b2573d6000803e3d6000fd5b505050505b565b6124c23361318b565b6125055760408051600160e51b62461bcd0281526020600482015260096024820152600160b91b683737ba1030b236b4b702604482015290519081900360640190fd5b601154600160a81b900460ff16156125675760408051600160e51b62461bcd02815260206004820152600f60248201527f6d6574686f642064697361626c65640000000000000000000000000000000000604482015290519081900360640190fd5b6001601154600160a01b900460ff16600281111561258157fe5b146125ca5760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b60115460408051600160e01b6323b872dd0281523360048201523060248201526402540be400604482015290516001600160a01b03909216916323b872dd916064818101926020929091908290030181600087803b15801561262b57600080fd5b505af115801561263f573d6000803e3d6000fd5b505050506040513d602081101561265557600080fd5b505161269557604051600160e51b62461bcd02815260040180806020018281038252602281526020018061372a6022913960400191505060405180910390fd5b60118054600160a01b60ff0219169055600b80546000190190819055610e10420163ffffffff16600f556000818152600a6020526040902060050154600160381b900460ff1615610b66576000908152600a60205260409020600501805467ff0000000000000019169055565b600c5481565b6127113361318b565b80156127275750601154600160a81b900460ff16155b156127e557600f5442116127775760408051600160e51b62461bcd02815260206004820152600c6024820152600160a01b6b696e76616c69642074696d6502604482015290519081900360640190fd5b61277f6131e6565b600b80546000199081016000908152600a602090815260408083208380526006018252808320869055935484519301835282015281517f775cbcccd7fe28145ecb9139488663063065c5a215ba96419500f1bb1217661e929181900390910190a1610b66565b600b80546000908152600a60209081526040808320338085526006909101835292819020859055925483519081529081019190915281517f775cbcccd7fe28145ecb9139488663063065c5a215ba96419500f1bb1217661e929181900390910190a150565b6011546001600160a01b031681565b612861613656565b60405180610140016040528060f084901c61ffff16815260200160e084901c61ffff16815260200160d084901c61ffff16815260200160c084901c61ffff16815260200160a084901c63ffffffff168152602001608084901c63ffffffff168152602001606084901c63ffffffff168152602001604084901c63ffffffff168152602001602084901c63ffffffff1681526020018363ffffffff168152509050919050565b61290e613675565b612916613675565b60ff80841660c0830152600884901c811660a0830152601084901c81166080830152601884901c81166060830152602084811c82166040840152602885901c821690830152603084901c1681529050919050565b612972613656565b61297a613656565b60c083015160f886901c9060ff60f088901c16906002820160031b600060105b828110156129c85760ff60f88290038c901c16848114156129bf5760019250506129c8565b5060080161299a565b5060006129d886868d8d8d6132f6565b90508015612aea578185036001831415612a02576129f98288036005612fa7565b82026101208901525b6001821115612ae8578260011415612a3357612a218288036004612fa7565b612a2c836002612fa7565b0260e08901525b6002821115612ae8576000612a4b8389036003612fa7565b612a56846003612fa7565b0284810260c08b01528281026101008b015290506003831115612ae657612a808389036002612fa7565b612a8b846004612fa7565b0284810260808b015282810260a08b015290506004831115612ae657612ab48389036001612fa7565b612abf846005612fa7565b0284810260408b015282810260608b015290506005831115612ae657838952602089018290525b505b505b50949998505050505050505050565b8051602082015160408301516060840151608085015160a08601516000958695909490939092909160085b60308111612b8e5760ff8b821c1684811015612b625787811480612b4757508681145b80612b5157508581145b15612b5d578860010198505b612b85565b84811480612b6f57508381145b80612b7957508281145b15612b85578860010198505b50600801612b24565b5086612ba4576000975050505050505050611aab565b8860c001518a60ff161415612c40578660011415612bcc57600a975050505050505050611aab565b8660021415612be5576008975050505050505050611aab565b8660031415612bfe576007975050505050505050611aab565b8660041415612c17576005975050505050505050611aab565b8660051415612c30576003975050505050505050611aab565b6001975050505050505050611aab565b6003871015612c59576000975050505050505050611aab565b8660031415612c72576009975050505050505050611aab565b8660041415612c8b576006975050505050505050611aab565b8660051415612ca4576004975050505050505050611aab565b6002975050505050505050611aab565b61012081015160009060208360086020020151901b60408460076020020151901b60608560066020020151901b60808660056020020151901b60a08760046020020151901b60c08860036020020151901b60d08960026020020151901b60e08a60016020020151901b60f08b60006020020151901b17171717171717171792915050565b60ff603082901c811690602883901c811690602084901c811690601885901c811690601086901c811690600887901c811690871660018110801590612d7e575060088111155b612dc05760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b6026821115612e075760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b828211612e4c5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b838311612e915760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b848411612ed65760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b858511612f1b5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b868611612f605760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b60018710156114f85760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b600081831015612fb957506000611aab565b81831415612fc957506001611aab565b60008284038310612fdc57828403612fde565b825b90508060011415612ff25783915050611aab565b80840360018101906002015b8581116130115790810290600101612ffe565b50600160025b83811161302a5790810290600101613017565b5080828161303457fe5b049350505050611aab565b600083835b838110156130a65760ff60f882900388901c1682811161309c5760408051600160e51b62461bcd02815260206004820152600e602482015260008051602061374c833981519152604482015290519081900360640190fd5b9150600801613044565b5095945050505050565b60118054600160a01b60ff021916600160a11b1790556130ce6136ec565b6130d782613452565b905060006130e98360060160086135d9565b60010190508060088360056020020151901b60108460046020020151901b60188560036020020151901b60208660026006811061312257fe5b6020020151901b60288760016020020151901b60308860006020020151901b171717171717600a60006001600b5403815260200190815260200160002060050160006101000a81548166ffffffffffffff021916908366ffffffffffffff160217905550505050565b6001600160a01b03811660009081526001602052604081205460ff1680611aab5750506000546001600160a01b0390811691161490565b60408051602080820193909352815180820384018152908201909152805191012090565b6000601154600160a01b900460ff16600281111561320057fe5b146132495760408051600160e51b62461bcd02815260206004820152600e6024820152600160901b6d696e76616c69642073746174757302604482015290519081900360640190fd5b6000613253611c10565b90506305f5e1008110156132a95760408051600160e51b62461bcd0281526020600482015260126024820152600160701b71696e73756666696369656e74206d6f6e657902604482015290519081900360640190fd5b600b80546000908152600a6020526040902080546000194301400190558054600101905560118054600160a01b60ff021916600160a01b1790554260f001600e556305f5e0ff1901600c55565b8051602082015160408301516060840151608085015160a086015160009586959094909390929091866003601e8e90038f11613337578d8f0160020161333a565b60205b901b905060028d0160031b5b818110156133b55760ff60f88290038e901c1685811015613389578881148061336e57508781145b8061337857508681145b15613384578960010199505b6133ac565b8581148061339657508481145b806133a057508381145b156133ac578960010199505b50600801613346565b508c601e038e1115613440575060088d8d01601d19010260005b8181101561343e5760ff60f88290038d901c168581101561341257888114806133f757508781145b8061340157508681145b1561340d578960010199505b613435565b8581148061341f57508481145b8061342957508381145b15613435578960010199505b506008016133cf565b505b50959c9b505050505050505050505050565b61345a6136ec565b6134626136ec565b61346a61370a565b60005b600681101561350457600081613488838801846026036135d9565b019050600083836026811061349957fe5b6020020151905060008483602681106134ae57fe5b6020020151905081156134c157816134c6565b836001015b8584602681106134d257fe5b602002015280156134e357806134e8565b826001015b8585602681106134f457fe5b602002015250505060010161346d565b5060005b600681101561353b5781816026811061351d57fe5b602002015183826006811061352e57fe5b6020020152600101613508565b5060015b60068110156135d057600083826006811061355657fe5b60200201519050815b60008111801561358157508185600183036006811061357a57fe5b6020020151115b156135b45784600182036006811061359557fe5b60200201518582600681106135a657fe5b60200201526000190161355f565b818582600681106135c157fe5b6020020152505060010161353f565b50909392505050565b6000816135e5846131c2565b816135ec57fe5b069392505050565b6040518061010001604052806000815260200160008152602001600081526020016000815260200160006001600160801b0316815260200160006001600160801b03168152602001600066ffffffffffffff1681526020016000151581525090565b604051806101400160405280600a906020820280388339509192915050565b6040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b604051806040016040528060008152602001600081525090565b6040518060c001604052806006906020820280388339509192915050565b604051806104c00160405280602690602082028038833950919291505056fe696e73756666696369656e74206d6f6e6579206f72206e6f7420617070726f766564696e76616c6964206e756d626572000000000000000000000000000000000000a165627a7a72305820b1048538cbbafc97df106db92d6a5ebccd84e57642875c04cd1d4acf5a6046100029")
-
- # TODO: TEST signature later
- def test_get_sign(self):
- address = in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- message = "0x000000000"
- rpc = in3.eth.account.sign(address=address, data=message)
- print(rpc)
-
- # TODO: test it later
- def test_send_transaction(self):
- _from = in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE")
- transaction = in3.eth.Transaction(_from=_from)
- rpc = in3.client.send_transaction(transaction=transaction)
- print(rpc)
-
- def test_send_raw_transaction(self):
- # it will fail if we didn't update the nonce
- data = "0xf8674184ee6b2800831e848094a87bfff94092281a435c243e6e10f9a7fc594d26830f42408078a06f7d65ea8a4d69c41f8c824afb2b2e6d2bc2622d9d906b0ea8d45b39f4853931a062ad406c693c629d8a4a1af29d21e672d11c577a5a220267562bb10612c8eab7"
- rpc = self.client.eth.send_raw_transaction(data=data)
- print(rpc)
-
- def test_call(self):
- # _from = in3.eth.Address("0x132D2A325b8d588cFB9C1188daDdD4d00193E028")
- to = in3.eth.Address("0x7ceabea4AA352b10fBCa48e6E8015bC73687ABD4")
- transaction = in3.eth.Transaction(to=to)
- transaction.data = "0xa9c70686"
- rpc = self.client.eth.call(transaction=transaction, block_number=in3.BlockStatus.LATEST)
- print(rpc)
-
- def test_estimate_gas(self):
- _from = in3.eth.Address("0x132D2A325b8d588cFB9C1188daDdD4d00193E028")
- to = in3.eth.Address("0xF5FEb05CA1b451d60b343f5Ee12df2Cc4ce2691B")
- transaction = in3.eth.Transaction(_from=_from, to=to)
-
- transaction.data = "0x9a5c90aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000015094fc63f03e46fa211eb5708088dda62782dc4000000000000000000000000000000000000000000000004563918244f400000"
- rpc = self.client.eth.estimate_gas(transaction=transaction)
- self.assertIsNotNone(rpc)
-
- def test_get_block_by_hash(self):
- hash_obj = in3.eth.Hash("0x85cf1fedb76d721bddb4197735e77b31d40e8b4f2e4e30b44fa993141b0a85d6")
- rpc = self.client.eth.get_block_by_hash(hash_obj=hash_obj, get_full_block=False)
-
- self.assertIsNotNone(rpc.transactions)
- isEql = in3.eth.Hash("0x4d162e12901d1a0a0236793cc578db3b16117b276740e777c0e449478ce1239c").__eq__(rpc.transactions[0])
- self.assertTrue(isEql)
- self.assertEqual(rpc.number, 16089542)
-
- def test_get_block_by_hash_and_return_all_transactions_data(self):
- hash_obj = in3.eth.Hash("0x85cf1fedb76d721bddb4197735e77b31d40e8b4f2e4e30b44fa993141b0a85d6")
- rpc = self.client.eth.get_block_by_hash(hash_obj=hash_obj, get_full_block=True)
-
- self.assertIsNotNone(rpc.transactions)
- self.assertEqual(rpc.number, 16089542)
- self.assertIsNotNone(rpc.transactions[0].From)
+ self.assertGreater(result, 1000)
def test_get_block_by_number(self):
- number = 16027463
- rpc = self.client.eth.get_block_by_number(block_number=number)
- self.assertEqual(rpc.number, 16027463)
+ block = self.client.eth.block_by_number(9937218)
+ self.assertIsInstance(block, in3.eth.Block)
+ block = self.client.eth.block_by_number('latest')
+ self.assertIsInstance(block, in3.eth.Block)
def test_get_transaction_by_hash(self):
- hash_obj = in3.eth.Hash("0x5774bfec01b1fbc44d7b828bb77b789f7f2779b59e47b3c9f167a6e9946db2f1")
- rpc = self.client.eth.get_transaction_by_hash(tx_hash=hash_obj)
- self.assertEqual(rpc.From, "0x10f7fc1f91ba351f9c629c5947ad69bd03c05b96")
-
- def test_get_transaction_by_block_hash_and_index(self):
- hash_obj = in3.eth.Hash("0xc45d36c9ef34bdb174c065463aeb9775f729db63577add69e5f629917d77e646")
- index = 0
- result = self.client.eth.get_transaction_by_block_hash_and_index(block_hash=hash_obj, index=index)
- self.assertIsNotNone(result.blockHash)
-
- def test_get_transaction_by_block_number_and_index(self):
- block_number = 15385949
- index = 0
- result = self.client.eth.get_transaction_by_block_number_and_index(number=block_number, index=index)
- self.assertIsNotNone(result.blockHash)
-
- def test_get_transaction_receipt(self):
- hash_obj = in3.eth.Hash("0x5774bfec01b1fbc44d7b828bb77b789f7f2779b59e47b3c9f167a6e9946db2f1")
- result = self.client.eth.get_transaction_receipt(tx_hash=hash_obj)
- self.assertIsNotNone(result.blockHash)
-
- # removed
- # in3.model.exception.In3RequestException: {'code': -32600, 'message': 'method eth_pendingTransactions is not supported or unknown'}
- # def test_pending_transactions(self):
- # result = self.client.eth.pending_transactions()
- # print(result)
-
- # removed
- # in3.model.exception.In3RequestException: {'code': -4, 'message': '[0x1]:The Method cannot be verified with eth_nano!'}
- # def test_get_uncle_by_block_hash_and_index(self):
- # # check later for the uncle by block
- # hash_obj = in3.eth.Hash("0xa2163d7d18578e0995b1304003b857337eaa4534cbe64905c7bd45a744932f1f")
- # index = 0
- # result = self.client.eth.get_uncle_by_block_hash_and_index(block_hash=hash_obj, index=index)
- # print(result)
-
- # removed
- # in3.model.exception.In3RequestException: {'code': -4, 'message': '[0x1]:The Method cannot be verified with eth_nano!'}
- # def test_get_uncle_by_block_number_and_index(self):
- # # check later for the uncle by block
- # block_number = 5066978
- # index = 0
- # result = self.client.eth.get_uncle_by_block_number_and_index(number=block_number, index=index)
- # print(result)
-
- def test_new_filter(self):
- filter_obj = in3.eth.Filter(fromBlock=16095289)
- response = self.client.eth.new_filter(filter=filter_obj)
- self.assertEqual(response, "0x1")
- import time
+ tx_hash = '0xae25a4b673bd87f40ea147a5506cb2ffb38e32ec1efc372c6730a5ba50668ae3'
+ tx = self.client.eth.transaction_by_hash(tx_hash)
+ self.assertIsInstance(tx, in3.eth.Transaction)
+ self.assertEqual(tx_hash, tx.hash)
- time.sleep(1)
- changes = self.client.eth.get_filter_logs(filter_id=response)
- print(changes)
+ def test_get_tx_receipt(self):
+ tx_hash = '0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc'
+ result = self.client.eth.transaction_receipt(tx_hash)
+ self.assertIsInstance(result, in3.eth.TransactionReceipt)
- def test_new_block_filter(self):
- filter_obj = self.client.eth.new_block_filter()
- import time
- time.sleep(10)
- changes = self.client.eth.get_filter_changes(filter_id=filter_obj)
- for c in changes:
- block = self.client.eth.get_block_by_hash(c,False)
- self.assertIsNotNone(block.hash)
- self.assertTrue(len(changes)>0)
- self.assertEqual(filter_obj, "0x1")
+class EthereumGoerliTest(EthereumTest):
- # removed
- # {'code': -3, 'message': 'The request could not be handled pending filter not supported'}
- # def test_new_pending_transaction_filter(self):
- # filter_obj = self.client.eth.new_pending_transaction_filter()
- # print(filter_obj)
-
- def test_uninstall_filter(self):
- filter_obj = in3.eth.Filter(fromBlock=in3.BlockStatus.LATEST, toBlock=in3.BlockStatus.EARLIEST,
- address=in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE"))
- response = self.client.eth.new_filter(filter=filter_obj)
- filter_id = int(response, 16)
- result = self.client.eth.uninstall_filter(filter_id=filter_id)
- self.assertTrue(result)
-
- # in3.model.exception.In3RequestException: {'code': -9, 'message': 'The request could not be handled failed to get filter changes internal error, call to eth_getLogs failed E'}
- def test_get_filter_changes(self):
- filter_obj = in3.eth.Filter(fromBlock=in3.BlockStatus.LATEST, toBlock=in3.BlockStatus.EARLIEST,
- address=in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE"))
- response = self.client.eth.new_filter(filter=filter_obj)
- filter_id = int(response, 16)
- filter = self.client.eth.get_filter_changes(filter_id=filter_id)
- print(filter)
+ def setUp(self):
+ # self.client = in3.Client('goerli', in3_config=mock_config)
+ self.client = in3.Client('goerli', in3_config=mock_config, transport=mock_transport)
- # removed
- # in3.model.exception.In3RequestException: {'code': -32600, 'message': 'method eth_getFilterLogs is not supported or unknown'}
- # def test_get_filter_logs(self):
- # filter_obj = in3.eth.Filter(fromBlock=in3.BlockStatus.LATEST, toBlock=in3.BlockStatus.EARLIEST,
- # address=in3.eth.Address("0x9E52Ee6Acd6E7F55e860844d487556f8Cbe2BAEE"))
- # response = self.client.eth.new_filter(filter=filter_obj)
- # filter_id = int(response, 16)
- # result = self.client.eth.get_filter_logs(filter_id=filter_id)
- # print(result)
+ def test_get_block_by_number(self):
+ block = self.client.eth.block_by_number(2581719)
+ self.assertIsInstance(block, in3.eth.Block)
+ block = self.client.eth.block_by_number('latest')
+ self.assertIsInstance(block, in3.eth.Block)
- # TODO: Fix
- # in3.model.exception.In3RequestException: {'code': -32600, 'message': 'eth_getLogs : params[0].fromBlock (a quantity hex number) should match pattern "^0x(0|[a-fA-F1-9]+[a-fA-F0-9]*)$"'}
- def test_get_logs(self):
- filter_obj = in3.eth.Filter(fromBlock=16095389, toBlock=in3.BlockStatus.LATEST)
- logs = self.client.eth.get_logs(from_filter=filter_obj)
- self.assertTrue(logs)
+ def test_get_transaction_by_hash(self):
+ tx_hash = '0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd'
+ tx = self.client.eth.transaction_by_hash(tx_hash)
+ self.assertIsInstance(tx, in3.eth.Transaction)
+ self.assertEqual(tx_hash, tx.hash)
+ def test_get_tx_receipt(self):
+ tx_hash = '0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd'
+ result = self.client.eth.transaction_receipt(tx_hash)
+ self.assertIsInstance(result, in3.eth.TransactionReceipt)
- def test_prepare_transaction(self):
- aux = {
- 'to': '0xA87BFff94092281a435c243e6e10F9a7Fc594d26',
- 'value': 1000000,
- 'gas': 2000000,
- 'nonce': 78,
- 'gasPrice': 5000000000,
- 'chainId': hex(42)
- }
+class EthereumKovanTest(EthereumTest):
- to = Address("0xA87BFff94092281a435c243e6e10F9a7Fc594d26")
- transaction = Transaction(to=to, value=1000000, gasPrice=5000000000, gas=2000000, nonce=78)
+ def setUp(self):
+ # self.client = in3.Client('kovan', in3_config=mock_config)
+ self.client = in3.Client('kovan', in3_config=mock_config, transport=mock_transport)
- transaction_str = in3.client.prepare_transaction(transaction)
- print(transaction_str)
+ def test_get_block_by_number(self):
+ block = self.client.eth.block_by_number(18135233)
+ self.assertIsInstance(block, in3.eth.Block)
+ block = self.client.eth.block_by_number('latest')
+ self.assertIsInstance(block, in3.eth.Block)
+ def test_get_transaction_by_hash(self):
+ tx_hash = '0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4'
+ tx = self.client.eth.transaction_by_hash(tx_hash)
+ self.assertIsInstance(tx, in3.eth.Transaction)
+ self.assertEqual(tx_hash, tx.hash)
- def test_signature(self):
- size = "0xf868"
- transaction_signature ="4e85012a05f200831e848094a87bfff94092281a435c243e6e10f9a7fc594d26830f424080"
- appended = "77a00e812f21c773ffd8e39da74371dfd5d1f0b626af1fd4d493880e6face4acd094a025ad6e719ba2b51b3407ef6dc71e2f9dbe81ab37986c04d270c7330b715027d1"
+ def test_get_tx_receipt(self):
+ tx_hash = '0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4'
+ result = self.client.eth.transaction_receipt(tx_hash)
+ self.assertIsInstance(result, in3.eth.TransactionReceipt)
- in3.client.send_transaction(size + transaction_signature + appended)
if __name__ == '__main__':
unittest.main()
diff --git a/python/tests/integrated/eth_contract_test.py b/python/tests/integrated/eth_contract_test.py
new file mode 100644
index 000000000..4c35f4a91
--- /dev/null
+++ b/python/tests/integrated/eth_contract_test.py
@@ -0,0 +1,137 @@
+"""
+Integrated tests for `in3.eth.contract` module.
+"""
+import unittest
+
+import in3
+from tests.mock.config import mock_config
+from tests.transport import mock_transport
+
+
+class MainNetContractTest(unittest.TestCase):
+
+ def setUp(self):
+ # self.client = in3.Client(in3_config=mock_config)
+ self.client = in3.Client(in3_config=mock_config, transport=mock_transport)
+
+ def test_eth_call(self):
+ tx = {
+ "to": '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ "data": '0x02571be34a17491df266270a8801cee362535e520a5d95896a719e4a7d869fb22a93162e'
+ }
+ transaction = in3.eth.NewTransaction(**tx)
+ address = self.client.eth.contract.call(transaction)
+ self.assertEqual(address, '0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308')
+
+ def test_get_storage_at(self):
+ storage = self.client.eth.contract.storage_at("0x3589d05a1ec4Af9f65b0E5554e645707775Ee43C", 1)
+ self.assertEqual(storage, '0x000000000000000000000000000000000000000000000000000000647261676f')
+
+ def test_get_code(self):
+ code = self.client.eth.contract.code("0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e")
+ self.assertEqual(len(code), 10694)
+
+ def test_abi_encode(self):
+ params = "(address,string)", "0x1234567890123456789012345678901234567890", "xyz"
+ encoded = self.client.eth.contract.encode(*params)
+ expected = "0xdd06c847000000000000000000000000123456789012345678901234567890123456789000000000000000000000" + \
+ "0000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000" + \
+ "0000000000000378797a0000000000000000000000000000000000000000000000000000000000"
+ self.assertEqual(encoded, expected)
+ params = "(address,string)", "1234567890123456789012345678901234567890", "xyz"
+ encoded = self.client.eth.contract.encode(*params)
+ expected = "0xdd06c847000000000000000000000000000000000000000000000000313233343536373839303132333435363738" + \
+ "3930313233343536373839303132333435363738393000000000000000000000000000000000000000000000000000" + \
+ "0000000000000378797a0000000000000000000000000000000000000000000000000000000000"
+ self.assertEqual(encoded, expected)
+ params = "getData(address,string,uint8,string)", "0x1234567890123456789012345678901234567890", \
+ "xyz", "0xff", "abc"
+ expected = "0x597574130000000000000000000000001234567890123456789012345678901234567890000000000000000000000" + \
+ "00000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000" + \
+ "0000000000ff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000" + \
+ "00000000000000000000000000000000000000000000378797a00000000000000000000000000000000000000000000" + \
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000361626300000000000" + \
+ "00000000000000000000000000000000000000000000000"
+ encoded = self.client.eth.contract.encode(*params)
+ self.assertEqual(encoded, expected)
+ err0 = "address,string,uint8,string", "0x1234567890123456789012345678901234567890", "xyz", "0xff", "abc"
+ err1 = "()", "0x1234567890123456789012345678901234567890"
+ err2 = "(test)", "0x1234567890123456789012345678901234567890"
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.encode(*err0)
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.encode(*err1)
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.encode(*err2)
+
+ def test_abi_decode(self):
+ err0 = "address,string,uint8,string", "0x0000000000000000000000001234567890123456789012345678901234567"
+ err1 = "()", "0x0000000000000000000000001234567890123456789012345678901234567"
+ err2 = "(test)", "0x0000000000000000000000001234567890123456789012345678901234567"
+ err3 = "(address,uint256)", "0000000000000000000000001234567890123456789012345678901234567"
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.decode(*err0)
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.decode(*err1)
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.decode(*err2)
+ with self.assertRaises(AssertionError):
+ self.client.eth.contract.decode(*err3)
+ params = "(address,uint256)", "0x0000000000000000000000001234567890123456789012345678901234567890000000000" + \
+ "0000000000000000000000000000000000000000000000000000005"
+ expected = ['0x1234567890123456789012345678901234567890', '0x05']
+ decoded = self.client.eth.contract.decode(*params)
+ self.assertEqual(decoded, expected)
+ params = "(address,string,uint8,string)", \
+ "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000" + \
+ "00000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000" + \
+ "ff00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000" + \
+ "0000000000000000000000000000000000378797a000000000000000000000000000000000000000000000000000000" + \
+ "00000000000000000000000000000000000000000000000000000000000000000003616263000000000000000000000" + \
+ "0000000000000000000000000000000000000"
+ expected = ["0x1234567890123456789012345678901234567890", "xyz", "0xff", "abc"]
+ decoded = self.client.eth.contract.decode(*params)
+ self.assertEqual(decoded, expected)
+
+
+class GoerliContractTest(MainNetContractTest):
+
+ def setUp(self):
+ # self.client = in3.Client('goerli', in3_config=mock_config)
+ self.client = in3.Client('goerli', in3_config=mock_config, transport=mock_transport)
+
+ def test_eth_call(self):
+ tx = {
+ "to": '0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e',
+ "data": '0x02571be34a17491df266270a8801cee362535e520a5d95896a719e4a7d869fb22a93162e'
+ }
+ transaction = in3.eth.NewTransaction(**tx)
+ address = self.client.eth.contract.call(transaction)
+ self.assertEqual(address, '0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308')
+
+ def test_get_storage_at(self):
+ storage = self.client.eth.contract.storage_at("0x4B1488B7a6B320d2D721406204aBc3eeAa9AD329", 1)
+ self.assertEqual(storage, '0x0')
+
+ def test_get_code(self):
+ code = self.client.eth.contract.code("0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e")
+ self.assertEqual(len(code), 10694)
+
+
+class KovanContractTest(MainNetContractTest):
+
+ def setUp(self):
+ # self.client = in3.Client('kovan', in3_config=mock_config)
+ self.client = in3.Client('kovan', in3_config=mock_config, transport=mock_transport)
+
+ def test_eth_call(self):
+ # TODO: Future
+ return
+
+ def test_get_storage_at(self):
+ # TODO: Future
+ return
+
+ def test_get_code(self):
+ # TODO: Future
+ return
diff --git a/python/tests/integrated/in3_client_test.py b/python/tests/integrated/in3_client_test.py
deleted file mode 100644
index 06d64e8b5..000000000
--- a/python/tests/integrated/in3_client_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import unittest
-import in3
-
-
-class In3ClientTest(unittest.TestCase):
-
- def setUp(self):
- self.in3client = in3.Client()
-
- def test_configure(self):
- client = in3.Client(in3.ClientConfig())
- self.assertIsNotNone(client)
- client = in3.Client(in3.ClientConfig(chainId=str(in3.Chain.MAINNET)))
- self.assertIsNotNone(client)
- client = in3.Client(str(in3.Chain.MAINNET))
- self.assertIsNotNone(client)
- client = in3.Client('mainnet')
- self.assertIsNotNone(client)
-
- def test_node_list(self):
- nl = self.in3client.node_list()
- self.assertIsInstance(nl, in3.NodeList)
-
- def test_abi_encode(self):
- # TODO: Check abi encode mock data
- param1 = ""
- param2 = 123
- encoded_evm_rpc = self.in3client.abi_encode("", param1, param2)
- self.assertEqual(encoded_evm_rpc, "")
-
- def test_abi_decode(self):
- # TODO: Check abi decode mock data
- param1, param2 = self.in3client.abi_decode("", "")
- self.assertEqual(param1, "")
- self.assertEqual(param2, 123)
-
- def test_abi_encode2(self):
- encoded = self.client.eth.account.abi_encode("getBalance(address)", ["0x1234567890123456789012345678901234567890"])
- self.assertEqual("0xf8b2cb4f0000000000000000000000001234567890123456789012345678901234567890", encoded)
-
- def test_abi_decode2(self):
- decoded = self.client.eth.account.abi_decode("(address,uint256)", "0x00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000005")
- add0, add1 = decoded
- self.assertEqual(add0, "0x1234567890123456789012345678901234567890")
- self.assertEqual(add1, "0x05")
-
-
-class In3ClientKovanTest(In3ClientTest):
-
- def setUp(self):
- self.in3client = in3.Client('kovan')
-
- def test_configure(self):
- client = in3.Client(in3.ClientConfig(chainId=str(in3.Chain.KOVAN)))
- self.assertIsNotNone(client)
- client = in3.Client(str(in3.Chain.KOVAN))
- self.assertIsNotNone(client)
-
-
-class In3ClientGoerliTest(In3ClientTest):
-
- def setUp(self):
- self.in3client = in3.Client('goerli')
-
- def test_configure(self):
- client = in3.Client(in3.ClientConfig(chainId=str(in3.Chain.GOERLI)))
- self.assertIsNotNone(client)
- client = in3.Client(str(in3.Chain.GOERLI))
- self.assertIsNotNone(client)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/tests/mock/__init__.py b/python/tests/mock/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/python/tests/mock/config.py b/python/tests/mock/config.py
new file mode 100644
index 000000000..5eb61d7f9
--- /dev/null
+++ b/python/tests/mock/config.py
@@ -0,0 +1,31 @@
+"""
+Configuration for `in3.client.Client`. Enables mocked in3 network responses to be valid.
+Disable node list updates, and collect signed responses from both boot nodes.
+"""
+from in3 import ClientConfig
+
+_registry = {
+ '0x1': {
+ 'contract': '0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f',
+ 'registryId': '0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb',
+ 'needsUpdate': False,
+ 'avgBlockTime': 15},
+ '0x5': {
+ 'contract': '0x5f51e413581dd76759e9eed51e63d14c8d1379c8',
+ 'registryId': '0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea',
+ 'needsUpdate': False,
+ 'avgBlockTime': 15},
+ '0x2a': {
+ 'contract': '0x4c396dcf50ac396e5fdea18163251699b5fcca25',
+ 'registryId': '0x92eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf',
+ 'needsUpdate': False,
+ 'avgBlockTime': 6},
+}
+
+mock_config = ClientConfig(node_list_auto_update=False,
+ node_signature_consensus=2,
+ node_signatures=2,
+ request_retries=1,
+ in3_registry=_registry,
+ cached_blocks=0,
+ cached_code_bytes=0)
diff --git a/python/tests/mock/http_fail.py b/python/tests/mock/http_fail.py
new file mode 100644
index 000000000..de982e99e
--- /dev/null
+++ b/python/tests/mock/http_fail.py
@@ -0,0 +1,109 @@
+"""
+In3 Network mock responses.
+"""
+data = {
+ "in3_nodeList": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_blockNumber": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getBlockByNumber": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getStorageAt": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getTransactionByHash": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getBalance": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_estimateGas": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getTransactionCount": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_gasPrice": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_sendRawTransaction": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getTransactionReceipt": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_call": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1,"in3":{"proof":{"type":"callProof","block":"0xf9025ca06dc0a75fd37144c278d2257ff3bffdbfbe3220985bb6dab757b65d58ce30b775a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a062953511938b2abeba31738bbe902528f11b93d0c52bb05840391bad08a38cc1a0be1cb2b843f4f44de360e53353eafd5a9e744a97339fe07a0c7df6537af13daea0bbac8b90441cbbd462d249962aee142e3e2fc21eb09dead2bc9a982f3d9e34c9b90100000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000283288608837a120083058184845eb436f4b8614e65746865726d696e6420312e382e32392d33392d3738636338353734352d3276f8ff571ac0aa8b2303ffeeea04dcc1fc63fab51cb083bd7ea9db2e16506664185a018a95ded01e5fea512d82c7f502e11c5ce60f0a625b9048d913519c700401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[],"accounts":{"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e":{"accountProof":["0xf90211a025f7837828900381549226ed62d8cf5fe8467e5215867d08949d315e2d0d5e54a0a4880b57c7f955d530fb9db12cc014f06d2662acc20ba1766e6fde46568d88afa0ececa23708fda597a6e219015a671e58144b451db8ec55ac526cd52e4dcf27e3a05bcd939273b5ec0b68b784079918ffa193a384951a2f4ae16211e3e51dea5983a0fad6a8bfa82e86f8f767c8e0111419813ac0f0b74ff0421de950320d8319f76aa060865d1b28d6b806d88d93a47f9ba063ac938c48f79ff1079a9a076f80a1bd76a099def635fac7b434b7bd27419020f7414e613024588c4fd3cd0d0c30e8e1266ea0748cc50e7fb2ac86efb0c3854cdbf55322e1201758e1e8d25509889c82bedc37a0a6a876a0f99ea780439206e73b1d380713e558f2dcb22597ea44055a5ca79a8ba0d0167541c69531286a662fd1712f27865fc920cec52513c7069f9d2a1a6528eea0b9c473dd97da6ea2b2fd23efed7869ace38015a1dcd5dea42fd7cddad75297f3a09dba136066e67d710348402c38deb5f9b58273fc7c20acbdc278c3116648517ea0703e358df413373543ea46a70414fbd70ad4bf68645b320ae80d97fac1dff0b9a0495929857ae83444acb9a3d63739ea5997043061be4691c8b537a00eef43d770a0fa69a385f4bc87dd0220c03c34ea9570eac40a211d7b2c509b51b55ff2c2a5e1a0ef6dee5b59b29c4ff46ace2f926c43623ded9a38e7f3f35ee2bbcccdf59c95f180","0xf90211a086f598f425869c690a42ee7080d2a07f70a3980a71d05bde86734c4b1cce4ccba0b2e87c0b3e758efe350f3cf0612fa488dd0076b283269343a06051da9e74491fa059082373c553c5e50cf3f226e46ca1f670d5a6f9afb3e46683aeb432f064aee9a0e5a3196a4e51a1c9ee60c6e79b52086c93f7c22e5e6601f9255b237a41d1c94aa024dc6286e71d1ee6ac012a358bce14b453f30ea123020a04bd6a575362ea86e2a003cb5ca7dcfcb1e19cabfa5c014293704b93ba9661ab2fb74942a46bc1a45e14a0d9265c767072490a0cced09d450989428941b517e7de3ee5a71100c81f483cc6a034b2dee792194edbb7e61d8891e808bfa0372b25d22d879eeb1a62bd8f1764fda025e25fd3926252016e1fe33085479548d5f7254da6b2293d8bb2345b2ba50d22a078c528e6bf46faf7c6a9f463c2cb4af8d2e7a6bbe35292e5d3b81d8ae01409d0a007d2f3e913822860a61ad14db2ded60c1917ffaf9c8c180c46e0673df3642faaa0922ce3829789280db9f44da03f5112c0d5a5f7445d7976c34928309eab17162fa0a842942c4d8dccbf3c84aabc22cd36eb8f9e729067040a41ba521f2acfc72ba5a095bc097d9b10e6c675d50f8d9e5b5054725ae15c928181a34ff633ae3465f3b8a0c3cfcc19f2ba2f67bec07fb3691beb4af24c316332b9315bf27142889919ee48a0cfd8d362be0586cc5da28905d14ca91c0d2d453a73dfce3f1ffeacbf948bf0ee80","0xf90211a04f342d34ff46e6afa5bbe57bf64a50bfe9f45b18d698771f14ad523ca9204735a0d6e7a21ab7e54ecbec333edc59d8dc6c5a52d59c779f15c4e0bd08c9880e4f18a0b74802cbb7f11b308c342d6a53e23ce6db271bb70aa620a4b21b375d1af54a1da0b36eb63c7ee8b48adaa5c459a739e69e48c690488a627e8913c4989d148e373fa098137a7a015cb87357d98b674fa487419b638dcb06c6c71db4bfed5a3a333b2ca04f0bd9062f6c40a94162a6384111afdfd4ea7bdaa9d5436032930b51da40694da02a6281bc68c6e521ac12346ee77e34a7919386244539041fd2f99e40805d3059a0050072af13602aa725f08143af11f25866d6f431b2ed994db2759e1eb612b35fa0e65068c69a3a891264a5cf27de4fe7d2526f9fa35db9594116a5f616ecb97757a065a261e873a9fbe54145317cd1f2c115da980cfeb706a69c48f1427ea9807f38a0bcdcc47dc3c0a0fde2406211f1d51e29910172a748c007b101811c73a34e3feca077215b6bdf217edad70a9f6fb33e8aa01b1cf8c17040cb0d208976bf468d9033a067f3b37f5f1ba9862694b0707203e5ae79e3bca5c5b6194ddfbdcae38096d736a0846bc590bd0e893c8bac0e73a51ca1d0c65f4043e3b40a98f3a12dc1870c7642a0f9cb6a7d624f9c3e58a0d47dbdf0e5d9bc4e688990c522b5eba7825ca7c9f02ba0282ed7b5b6a0f8357789b26dfc9f26d57fa1bbaea96183c20c20dd656ab5de2980","0xf901b1a090180abf51ee9a8d06b322766f3cf17aade5f5606d54fc17844f062a105e4aaba016e7abe823e421a9e7e14e77f4897532e7bab0a64f8575e5ed988a5fa50376bca09fd4239f754ce994e3f05c29b0800c8fa29ea7476f3d1bb33afcc3b33029b04ea0c32c2ce9a42b69f26eb54ccf4f397f9fa5c64b1289972e00f5df914f3b867d8ea0339ffbbc8b267ba43b478c855cf7c3b65b5681198dbe14a6c383d6e927fb99f1a0ced10e3fe79d30da075048d03fc402bbb227108dd076b22db793d4e0128022efa0c95784b61cd7b153e42c8e22d91028bcd9b7a440e8bed87d5f54cbfea185b05a80a0972fb1e7344edef25c975f7f827d6517616f9720370fa9a188bb37e8af072fd980a0d8dff14cd8d20fe86f1abcc1d12cc7004b5d82af5fa65b16c6593d6ae3e35d76a04b75c24381c9c971ab560c96baf1e65128510c2a7c71e73b7c4533424eb376d3a02933b22375eaa4148e5cf2f687209eb60f9fc3c93af79e7d09bb7a483e5c922380a07caa3f3785c08bc622dbd2b81f4437c95467a9f137a0e83ece5c5c236cbc03caa0e1f6bc975a6f522766aee88f41212e45ff4519a197cd665fba9421b0242d8bcf80","0xf851808080a027502d7195cb72082344b69d3de29c9a8b78d23d6e111f8b17bd6ab06206bac9808080808080a004765232d3d7c62b886a9855d8074b75a2b597b4dd7ad2e964ed0a0642cb1266808080808080","0xf8679e32ca53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0c3f929c1b1edec672bf94af2f29f6bf5f9c1b3d5aacb28567442044d7aca7bf2a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xc3f929c1b1edec672bf94af2f29f6bf5f9c1b3d5aacb28567442044d7aca7bf2","storageProof":[{"key":"0xf5b742b24dd65d70e890d260bae4623c81356ed4a2273eb5395b0ad001a3d426","proof":["0xf90211a094b692f2c6897bc55ef9acfbedb50a23b083ccbedb1af20586986413663e7621a090a2c5a9157bd4937729d9ad4a3c05bba846344f0a30c3c03231171e20bd6b0ea03df0618fb56d07beeed3d78b18ab1e6057fc9ed2c7fd7650dce93bda3ab33994a09951c2297d2dac4bbb59c9dc4024b017c5db3d9162acce71bdbc19cf8f107521a0b6ca3de8b4e68993184e5420a3b22ded792f2d54d59778fe746271b3398dc48da055a22af3a923f050f98ee5d40e1555b2afb6fae9e41c3ca511b33c1c79b23285a0ca58c99cc1689c31014bdc073d8abe497afe645f70ecf663a6033ee7d9a8b6c6a0d94a100b48436617d224aa38ecc7d0916a344f39917b317a79995a574826fb8ba0b7e42142ae07da09a385c8ea067c8d37c0d3e78ad8ded9e7757fdc4509beaa9da086522afc4a2fa26e6b458f9e58601e5647ada5f4f32c60bebe5c12e18805ede8a0e714cb494f402b72ae8239ef033b1db8a653b5e1e04cf6ff776f69d443ce2769a0b4ab0a070e9af3aa26c5fa090be6b232e836f1ed5afecea99db9ea8240e7c141a0be9791b8032d4733fcdbfdf10776af9c714e745ff736dccc1704459f2e0348b3a082edfdab8e14051844ec45ff83b0b61046c8e143bf025bb2224d61a97c540a90a043b790604937d3fa595c7fe6b4f71910c2adb993d730fc1fa08e93c106025bada0931b49f45973b2fa488db5a728da895d28e7d9ec48e6939a9677962eb8bed38780","0xf90211a057440af448fce6c3199f887e0f16aa68059c557f433a6a59822c7d3e00b407fba0884c6cdb957a90ff35a16d9992b21c3cd90ff9a7ac6c836423046f543178a19ca0a0c05ed74b622d677a2f9a8b45a66cb1d2cd490db5601e3cbe18800603b6f09aa0a0aecd7de59376d39cb6ae967fb7a6b40bb4b08e3de0dcb239b4b7f8a4c9a7fba0d115fbf083d8817f2908145db14034c5f04d657018afb1258b536224c60eb7e2a0e2a269d95c7f62e0acfd087c2f21bd8a44e784e1e17c609dc47205384eb7dd4ea0dd53cb77cc5450219d6df4831ca8ebcfa07655eca11600067a054375a2b3c817a01f060432fadd0673aa9555c3396aedccc911bcb0580c098915331fd4c9fc2a72a0ebca9ec2704b274326697aab522a2a7150b13d8da28599d271f1c58f919915e5a06822737b2cb9337f974ca353b955b3e869ab018e223cbcd2228394eabcd34d50a0b47758bef4afd19fcc6530625a48f80a3e0a409ff7896f3ea547517fec61dbbca0353d269126dcb4df48b75c76b1f046d1acc005bc0bc024483f472e5d63260af0a0ca8efd3537874a7f46e07bb1f790c8382c06165a0ded8e696302cd75cbdb013ba065e5ab38121e375ff9b8694f9703441ad8f801305561dba2573b8cd9af5da994a0446add3388f3778c318585c461e19a47672020fd0e3c2996be187ccf765a8d7ea064f85979a2243b032d1564eb4d7adcdba3c814d29222f83a9c13b79bbaa2f8e480","0xf7a02051c9113b510db4f54b92a2db3e9b4e59093ea5d33ba43f2dfb78ff6a84bdd195946587d6e907a0af73192b2d35dcf488fa1d06f9fa"],"value":"0x0"},{"key":"0x2","proof":["0xf90211a094b692f2c6897bc55ef9acfbedb50a23b083ccbedb1af20586986413663e7621a090a2c5a9157bd4937729d9ad4a3c05bba846344f0a30c3c03231171e20bd6b0ea03df0618fb56d07beeed3d78b18ab1e6057fc9ed2c7fd7650dce93bda3ab33994a09951c2297d2dac4bbb59c9dc4024b017c5db3d9162acce71bdbc19cf8f107521a0b6ca3de8b4e68993184e5420a3b22ded792f2d54d59778fe746271b3398dc48da055a22af3a923f050f98ee5d40e1555b2afb6fae9e41c3ca511b33c1c79b23285a0ca58c99cc1689c31014bdc073d8abe497afe645f70ecf663a6033ee7d9a8b6c6a0d94a100b48436617d224aa38ecc7d0916a344f39917b317a79995a574826fb8ba0b7e42142ae07da09a385c8ea067c8d37c0d3e78ad8ded9e7757fdc4509beaa9da086522afc4a2fa26e6b458f9e58601e5647ada5f4f32c60bebe5c12e18805ede8a0e714cb494f402b72ae8239ef033b1db8a653b5e1e04cf6ff776f69d443ce2769a0b4ab0a070e9af3aa26c5fa090be6b232e836f1ed5afecea99db9ea8240e7c141a0be9791b8032d4733fcdbfdf10776af9c714e745ff736dccc1704459f2e0348b3a082edfdab8e14051844ec45ff83b0b61046c8e143bf025bb2224d61a97c540a90a043b790604937d3fa595c7fe6b4f71910c2adb993d730fc1fa08e93c106025bada0931b49f45973b2fa488db5a728da895d28e7d9ec48e6939a9677962eb8bed38780","0xf901f1a0a813c6585cf56c6d39e48827788f0e479865d8d978347168f8555ef893e48ddfa0e409a771de608fc7a8727c9d5f2e1dc504500ee3a127f87bdff9c27f659a46f8a06cc104b3907853ec3dbaa86d231e96ec6d3254516fbc7d76202605afd67979dea0a8736730dcac4f8d5b58c7c7fdad18440c1c38a2de33f6e9c7bc114f27082871a0a1ef2b02b68a1dd6322fa8de3868c758bb2cab133fa75d7b02bf07f431406a9fa00f0e7fc6fabe2ce548329e693c6d2b92be9bf4f5119d8b2b31c0e5041034362ea061b35da30307184c72bfacbcfeb356f4f560939664872be4920147321bffc3d7a01b3835ce1b5b9ce25cb333f4672c3391052e7afbb2df8acf09f4e0e197997e35a008fd3760e169d8e0e85ff4500dd4644b8754eeef4c83b88eee453c072c23200e80a055f1da95430be0e9554f013602cbf7e9ac8f63869e295973771708d6eee85909a093a5c8371e345d5813359e74bb4386334f8ba148164f0e44dbc951133d929a13a0be23762b47da1df80ab681ead49911544faab33a83976e802ba861da11fefeaaa02f325673c20de1a63cd7ca4a767feee84572da1d6f620d8e441668d71cc97f7ba0f645fce4f3aca93d51d9630ae864f42f6d1fceee69bf72db711dab42d788121da041dfc758eb8cd07ff7a583c30388c11d0b86276807c00536c2867c8de9eda12380","0xf8f1808080a0019985c2f10ffd0b9d7ed087d669b058da1f3ade17b54291b0a29460f8fe11cca076228bf21c4d2e3bcf6786d3b30754e434c0f0ece4f792ff6f9bef3f5564afdfa09ec89ef39c32e710202a7a6c88e72a69d29d068a75e1243263f7b735a135b7bb80a04ffd1817305f293c126d364c22af34e7ae06082295e24d7a00af4068aaa5bcdc80a0e23419fc2e01dc9fcfbec084c26f6e7f2bf2b7db0be3abd321c930d52a93fc7f808080a08c4c224328b0f156615652029e12b74b6d2a348bf0e69378b844e700592ad48c80a0723e1d7ff8cb1f8edbe27af81ef055d2e456f273925377022f602bc20747d4e680","0xf851a047a4a8dbe64d9bc53acb9153b58dec3de1c7fa8bd40da5e99ec92d3f06c73661808080808080a0b8bb80708372646606dcf14a305877d1f9ad3a917b2b786a56328b4fba159aa9808080808080808080","0xf69f2087fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9594112234455c3a32fd11230c42e7bccd4a84e02010"],"value":"0x112234455c3a32fd11230c42e7bccd4a84e02010"},{"key":"0xf5b742b24dd65d70e890d260bae4623c81356ed4a2273eb5395b0ad001a3d427","proof":["0xf90211a094b692f2c6897bc55ef9acfbedb50a23b083ccbedb1af20586986413663e7621a090a2c5a9157bd4937729d9ad4a3c05bba846344f0a30c3c03231171e20bd6b0ea03df0618fb56d07beeed3d78b18ab1e6057fc9ed2c7fd7650dce93bda3ab33994a09951c2297d2dac4bbb59c9dc4024b017c5db3d9162acce71bdbc19cf8f107521a0b6ca3de8b4e68993184e5420a3b22ded792f2d54d59778fe746271b3398dc48da055a22af3a923f050f98ee5d40e1555b2afb6fae9e41c3ca511b33c1c79b23285a0ca58c99cc1689c31014bdc073d8abe497afe645f70ecf663a6033ee7d9a8b6c6a0d94a100b48436617d224aa38ecc7d0916a344f39917b317a79995a574826fb8ba0b7e42142ae07da09a385c8ea067c8d37c0d3e78ad8ded9e7757fdc4509beaa9da086522afc4a2fa26e6b458f9e58601e5647ada5f4f32c60bebe5c12e18805ede8a0e714cb494f402b72ae8239ef033b1db8a653b5e1e04cf6ff776f69d443ce2769a0b4ab0a070e9af3aa26c5fa090be6b232e836f1ed5afecea99db9ea8240e7c141a0be9791b8032d4733fcdbfdf10776af9c714e745ff736dccc1704459f2e0348b3a082edfdab8e14051844ec45ff83b0b61046c8e143bf025bb2224d61a97c540a90a043b790604937d3fa595c7fe6b4f71910c2adb993d730fc1fa08e93c106025bada0931b49f45973b2fa488db5a728da895d28e7d9ec48e6939a9677962eb8bed38780","0xf901f1a035ebadda0f06b8c53f8e71c4843175170f7fc250f12a4efebec74d5dc7cbb081a006f9aa892424f02fa94f42b5cc82f31838d02225130a8629228bc0fa114fa7cba0078b70a42c7d73d57fe73e76a6ba729af39415efebd6da31163c63d028d8f0fba0d5cd1906e43bb3c0f61b059cd2a499c01ac3bd1788dc38e5cef0e65862ba8a9880a0e4fcdaa954f46ba03ca9c55c1c11ad75559d0b4089cc68e2b33949bf75b29d6ea014d060659844ee294158ad0ea6fe7f0729cd7ebf0f93af37f7c49d237ee6431da01b2684b346e689b7a6a1dff48575c80fe528339e93e236e4f37363aba40adb84a00fe0c67457b8e09e05df278b513fd7e479fc0c925b1d004304e5dcbbfbf27f18a0db75723819d409b1da48fdb000ad407823b3751b68ef0151d20917ec28ce130da08b846f9ce3dc64a7dbdb261cc30e84061edc36898c83df90fad1a111f64ab61fa0f93b6706f5b136e6f1956bbd6cb98325682864fe1b0bdb7128a62605bd523680a0c7fce279486880e3629a2312320d48a054356b741b6fe5ab415ce4ab7f037917a072d84b6f048b3d037ac184442edbb50b569a1e35925738144f5ac59ffe966eb2a0231f24467c181c1ffe6b15aaaa465674805538d35265f2907f9604fe3b9e8b4ca0a255267ce54d7b2e73cfbb6f7b28c1a1acb872dd15e0d04cfb3c33950a90c84380","0xf8718080a090a999996c67e092715cae0a4fc52d442a5becea6daae6e85c0dba58c8c0fff8808080a08a7e70d5dd86932d17578489c82c28c9f26e470b6f298f949c6916c0e75214af80808080a04aacd5772728eec2b104bd1de56d2952dfbb0a0468f28f02aab045a26f04a38e8080808080"],"value":"0x0"}]},"0x112234455c3a32fd11230c42e7bccd4a84e02010":{"accountProof":["0xf90211a025f7837828900381549226ed62d8cf5fe8467e5215867d08949d315e2d0d5e54a0a4880b57c7f955d530fb9db12cc014f06d2662acc20ba1766e6fde46568d88afa0ececa23708fda597a6e219015a671e58144b451db8ec55ac526cd52e4dcf27e3a05bcd939273b5ec0b68b784079918ffa193a384951a2f4ae16211e3e51dea5983a0fad6a8bfa82e86f8f767c8e0111419813ac0f0b74ff0421de950320d8319f76aa060865d1b28d6b806d88d93a47f9ba063ac938c48f79ff1079a9a076f80a1bd76a099def635fac7b434b7bd27419020f7414e613024588c4fd3cd0d0c30e8e1266ea0748cc50e7fb2ac86efb0c3854cdbf55322e1201758e1e8d25509889c82bedc37a0a6a876a0f99ea780439206e73b1d380713e558f2dcb22597ea44055a5ca79a8ba0d0167541c69531286a662fd1712f27865fc920cec52513c7069f9d2a1a6528eea0b9c473dd97da6ea2b2fd23efed7869ace38015a1dcd5dea42fd7cddad75297f3a09dba136066e67d710348402c38deb5f9b58273fc7c20acbdc278c3116648517ea0703e358df413373543ea46a70414fbd70ad4bf68645b320ae80d97fac1dff0b9a0495929857ae83444acb9a3d63739ea5997043061be4691c8b537a00eef43d770a0fa69a385f4bc87dd0220c03c34ea9570eac40a211d7b2c509b51b55ff2c2a5e1a0ef6dee5b59b29c4ff46ace2f926c43623ded9a38e7f3f35ee2bbcccdf59c95f180","0xf90211a01541b7d2c862cb826ca876369763f88f83cf6ccd599c87c69f26ef8c7a569e4ea0a39de4f5538fe6dbd4dcb4828004ff6dc6a5dd77a731d92b920d7d30786aadcba062031be87620ec705761e69a4765c77c7dd295d59c22c2b077609ab4c5e8bc71a03fa7fa7a6506ab46187ac686db2f75857c4ec9e0c5ee3ffde303f5bd089a2c0ea0a69c6a554edcec51e1dbeb95ecfbfe22f5ba61911d96c361713221d96dbc5818a09dc20aa7e96a290fd105bb361bfc3486df4bd90b40a08a020ad567feb5bd9b27a059a228392df8f1615c2c3a2b9422d182623a8d343fe2eda1de7381ac43cd9216a0a6f4fb99d207044d6922861b456e1f88b9148606c95d9a11d553d7b7b360ed8fa0035eb08cfcf6360840f01aae4ade55c96a920e0af3848f77b1ea2d12a75b795ca0dd6b3fd4310d38ac94f5c2bb7bf8719967fc837ba404f9c0747b6492c8a6a628a012b1ba67cf88e85083453cf53dbd01c7e60f4ac1e6d072f5a444d2025a7f8c54a051dad24c7f319d7e70050a52316fa8512b9c1399fb6937e9458cbca95a857f16a05af254626d1c38d869c3a30c233d07c893e57f89e5fb996133ee02dfc41a3a77a05c9f81718c617504d9216bea16f192c57a55e96cbc11f9c1cd8cdc43c3f50170a0cd42510dd63f01d587ed779d4556d864328ed8aa8ac107d80b61661c4d11c7bfa0f88e8f12f4574458e9d37d641235ee298a709a2be53c7265a2cf3d81d1aed52780","0xf90211a0c730e2d6e9549998628cc9a77efe9eec4271c08301ec3ffd8e8268d44c37646ba00cb9a30565fc39a6fdedd510cdeba241c99812b18c290ee3488a672ece7d2e9fa0806249ae1441fbf0474a2c5847a64afc8bc9036eef67a5c38c685701b1875e5ca02e8efd3b6a1a3a32e8f6ec12af19585567e4e7714c5bcfe447f37479cb7c94b1a07537361f6f682eb9ced1f4568da1c5606785aaf0c5f4207903896048f7202ac4a01772dfaee918e45a4566ee1dbfdadf462d1cd8571630570f597a7fd669570a84a095556f5ca06dc0c961abb372a9aeb26843430a94e0c0bd12dc25ebc8735531b5a0bf889440350a3b3c71d15706ee04590f8c58720db13ddcc0db4170c2aeee3eb4a03b2183e068cd356360ab800b22124bf88b7ff34743fa49a0aa241bfd380cc918a0efb9d3b9a13a900409ed82ae00213ebdc1ae6b6857efd248bf1e345ffcdd60dda060e6feee2a6c3d02ddd51ea72cf44376040f608f850e4116be28c50abefd0571a05490a96b32dabe5455eeca7157c7c5ad91aef85f362a792f9cc0e665daa3b66da01623b4286960dcfc3533d4e5ba63b93e26bcd2c9a806eeb60171c980b0c3475da0bebfe943f7a83c0244c16f09197b8959d8cc5edd066ab1e772c6c9ffc46a0888a0857cfb922db03cc35d221a89daa74c6f316ae4700b90fc464e350a5aa5b252bfa0a787764e1e561daf57893bea2dde0956a08b527762194877b4e842a4c541740780","0xf901f1a08edf50b38fdd779a44db2bb2e946a29df932eaa5a39507cfcd8f2fb7a1cd8cc2a06f110925664586734829dc4e2072d7d17337dd477288625337e91ece0cd8d6fca01fb036d7c2d34f6628438139d8655066c73b328b2f7eee7b86e78bfa3faa5997a02516831fad23581f2695caccca6fe3574e042cec95623fb8bd5a49eefa363347a0ac9459b10ae5e60081a218fcee8cb128f98c8931c1813cb9a2b72b171a451ebfa0a12a5f12fcb35d64aa3d958fa5fd7bf0d75125bb23f79e17f4f56bbda19d0392a025e3600b0d477cf1eae61b5426f4f15e0e88a90ebcb17d072def1b954430a33aa0c452a1556c42838198ff5b126740f645743a4b5e64b461db3f4eacaaebc1f397a06198edf71ce8ea81b964b07749f72662271dbef056b4965bf51bd559e6faac73a0219ce4946a6e247b22d3329d046198926eed4b645d2debdc49ccb9c7927351cda0c9dd410f9cab9eac20166ebe5331e64cf068faf842b8f6fb178b8001af42565080a02bb3bbb5227e7646f0321e9345c7f9f3f904f906bede70aa80d68a02430402aba0e8a727912c23e1e164212a92b2e2b8d6713d65d1996205f29dac61e43f04a404a02fe748873384c34fe9b4d1a2f7a135d1c3ac0985a9a52bb9815980e8b9ac5622a04d69f394eed6db377012398e2d09204410b9a0c6e7993df209a2e45258ec576f80","0xf89180808080a078047c5444f60442cde68e14d2a5eafae32e8e01112d655e42fe243854cf2c3280808080808080a02da9588e883b83effc92279de896d88bb4aeb94d0356edd46dbbbad3b0865de880a07db374f07e5b92b64b46e23e46d1beeeedc9daf72aaa890712326c117d6a6cbfa0bbed040a0b628c3c024daffa627abe60acf0598ad165e711cc64841ede5f504d80","0xf8679e3f9519abbb2ddefdae25c76e806705c5b5b98bf99e7b670ef051d531ab6ab846f8440180a020cdfd50bff30ca638651e728738f9f20441f01dc3b874bbdaf3862f9404db2ea0fe7b7500be050a55d003217cac2f0baaa1de0a23a8ff92adcebe9d173a6551bf"],"address":"0x112234455c3a32fd11230c42e7bccd4a84e02010","balance":"0x0","codeHash":"0xfe7b7500be050a55d003217cac2f0baaa1de0a23a8ff92adcebe9d173a6551bf","nonce":"0x1","storageHash":"0x20cdfd50bff30ca638651e728738f9f20441f01dc3b874bbdaf3862f9404db2e","storageProof":[]}}},"version":"2.1.0","currentBlock":2655752,"lastValidatorChange":0,"lastNodeList":2607742,"execTime":311,"rpcTime":308,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getCode": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635b0fc9c31161008c578063b83f866311610066578063b83f86631461042c578063cf40882314610476578063e985e9c5146104f8578063f79fe53814610574576100cf565b80635b0fc9c3146103025780635ef2c7f014610350578063a22cb465146103dc576100cf565b80630178b8bf146100d457806302571be31461014257806306ab5923146101b057806314ab90381461021c57806316a25cbd1461025e5780631896f70a146102b4575b600080fd5b610100600480360360208110156100ea57600080fd5b81019080803590602001909291905050506105ba565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61016e6004803603602081101561015857600080fd5b810190808035906020019092919050505061068f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610206600480360360608110156101c657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610764565b6040518082815260200191505060405180910390f35b61025c6004803603604081101561023257600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610919565b005b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610aab565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b610300600480360360408110156102ca57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b80565b005b61034e6004803603604081101561031857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d42565b005b6103da600480360360a081101561036657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610eba565b005b61042a600480360360408110156103f257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610edc565b005b610434610fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f66004803603608081101561048c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050611003565b005b61055a6004803603604081101561050e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061101e565b604051808215151515815260200191505060405180910390f35b6105a06004803603602081101561058a57600080fd5b81019080803590602001909291905050506110b2565b604051808215151515815260200191505060405180910390f35b60006105c5826110b2565b61067e57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d602081101561066657600080fd5b8101908080519060200190929190505050905061068a565b61068782611120565b90505b919050565b600061069a826110b2565b61075357600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561071157600080fd5b505afa158015610725573d6000803e3d6000fd5b505050506040513d602081101561073b57600080fd5b8101908080519060200190929190505050905061075f565b61075c8261115f565b90505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806108615750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61086a57600080fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506108a781866111e2565b85877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610a145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610a1d57600080fd5b837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050565b6000610ab6826110b2565b610b6f57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166316a25cbd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b2d57600080fd5b505afa158015610b41573d6000803e3d6000fd5b505050506040513d6020811015610b5757600080fd5b81019080805190602001909291905050509050610b7b565b610b788261122f565b90505b919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c7b5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610c8457600080fd5b837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610e3d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610e4657600080fd5b610e5084846111e2565b837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610ec7868686610764565b9050610ed4818484611262565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61100d8484610d42565b611018848383611262565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111d85760009150506111dd565b809150505b919050565b6000819050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611220573090505b61122a8382611455565b505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611383578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611450578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a25b505050565b8060008084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea265627a7a72315820e307c1741e952c90d504ae303fa3fa1e5f6265200c65304d90abaa909d2dee4b64736f6c63430005100032","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2607743,"execTime":84,"rpcTime":84,"rpcCount":1,"currentBlock":2655759,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ }
+}
diff --git a/python/tests/mock/http_ok.py b/python/tests/mock/http_ok.py
new file mode 100644
index 000000000..ffcf0ad81
--- /dev/null
+++ b/python/tests/mock/http_ok.py
@@ -0,0 +1,109 @@
+"""
+In3 Network mock responses.
+"""
+data = {
+ "in3_nodeList": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/mainnet/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0xe043da617250000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224418,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x1be4f459be890000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224531,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x45871874b4b50000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224604,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x8aeaa9f6f9a90000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224650,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x115b1ccfb83910000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224948,"weight":2000},{"url":"http://eth-mainnet-01.incubed-node.de:8500","address":"0xe9a1f583c6591566b0cda30dd2a647126d1ce0c2","index":5,"deposit":"0x3782dace9d90000","props":"0x6000001dd","timeout":3456000,"registerTime":1578987329,"weight":2000},{"url":"https://in3-node-1.keil-connect.com","address":"0xcff39dbe511bcf14b65e4030b3d8700e0ed67cea","index":6,"deposit":"0x16345785d8a0000","props":"0x1f0e0000000a","timeout":3456000,"registerTime":1578988306,"weight":1},{"url":"https://in3-node-from.space","address":"0x792cc04f89b012ac1f98c19b7281fbda8a3e1a92","index":7,"deposit":"0x2386f26fc10000","props":"0xa000001d9","timeout":3456000,"registerTime":1579088618,"weight":1},{"url":"https://in3.iotenabler.com","address":"0xb8cf3f02c24ca897b157a34019711679c6e556a8","index":8,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579092616,"weight":1},{"url":"https://incubed.online","address":"0x77a4a0e80d7786dec85e3087cc1c6ac3802af9cd","index":9,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579247282,"weight":2000},{"url":"https://in3.indenwolken.tech","address":"0x591761898ba2dfcf3b230bd3ab7d0de0c4ef168f","index":10,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579252398,"weight":2000},{"url":"https://in3-g.open-dna.de","address":"0x0cea2ff03adcfa047e8f54f98d41d9147c3ccd4d","index":11,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579267585,"weight":2000},{"url":"https://in3.fri3dman.com","address":"0xb451c4b6bdfbc4123fdd7cf61fd9dc0a88021f65","index":12,"deposit":"0x2386f26fc10000","props":"0xa000001f9","timeout":3456000,"registerTime":1579352283,"weight":1},{"url":"https://in3-parity.iotenabler.com/","address":"0x4323d321a39ed4a197524c6acd18c072f753c1b0","index":13,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579525922,"weight":1},{"url":"https://in3-geth.iotenabler.com/","address":"0x8db016dbdc03e76990adda627aab64db8106be4b","index":14,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579526954,"weight":1},{"url":"https://in3-infura.iotenabler.com/","address":"0x19580b648bb23163136b583ff5f56657fffb6610","index":15,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579530461,"weight":1},{"url":"https://in3no.de","address":"0x65b9464bc41dc35534f8b6ea5108f4905161efd2","index":16,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579538640,"weight":1},{"url":"https://letsincubed.com","address":"0x1389e3b68bbef358e4ee6fabf94d3c884deda376","index":17,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579539143,"weight":1},{"url":"https://in3node.com","address":"0x00a329c0648769a73afac7f9381e08fb43dbea72","index":18,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579600645,"weight":2000},{"url":"https://chaind.de/eth/mainnet1","address":"0xccd12a2222995e62eca64426989c2688d828aa47","index":19,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579646966,"weight":1},{"url":"https://in3.tuc47.xyz","address":"0x6d172460c0303736c2fd4a329664fe03c2f09512","index":20,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579717924,"weight":1},{"url":"https://in3.ahnenposter.de","address":"0x6e314c4c7b5ae5c6f49aea2d90a1d083abab045d","index":21,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579764858,"weight":2000},{"url":"https://in3.themysteriousclown.com","address":"0xdaaf752eabf0dc0e8b0ef00045efed6cfda727d6","index":22,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1580328209,"weight":2000},{"url":"https://0001.mainnet.in3.anyblock.tools","address":"0x510ee7f6f198e018e3529164da2473a96eeb3dc8","index":23,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1580901801,"weight":1}],"contract":"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f","registryId":"0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb","lastBlockNumber":9935386,"totalServers":24},"jsonrpc":"2.0","in3":{"execTime":167,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90212a0e5034d87bb2aa4848c2724d24550ac1333ab454372bfece45fc95285ff286ac8a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794eea5b82b61424df8020f5fedd81767f2d0d25bfba017fac1ed901824132daea12eb7b9f24c99aeef140ac2c4b71cf566f5f52a1638a053f479812eb683d1fe3ef8997a7d441b11c963f94aab2154b0464d038a224519a0fabb38122a58a640ff27589f1fd8f21e908e72e4d140863c6a9919875fb6b010b901000008cca012e87919c419a49c4b6e18ac3af028a9d61ac0104088005002102b0086265017d6c025a21d84230b92020124920004220c494600f96560a120388435f4801018963b87b141e247880183400022d0e4440ae82acca24061a48248339a90000516a6e20010460b0aa0102c0828341430025796048a2000243653359a0c015421c20108544011242b80400584e131a00509c4301441351023352eb9008886154000780c0200711032806040944540200405e90a0c1500142a010c221c5082bc0022197099410203ea210410000d2866724708e400858d7b23d29c08316f8330e46b410208ad68e00f04c018860014348901a75d42c50965a00440500a488707e07aa5f4a65183979a1a839870538397da82845ea2e46c91424a30322f4254432e434f4d2f0001dc0ba0d7968248a360533b2f209205602815c8bf121a4cbcf5a1f55611b027e497d63c88633319f71b3af672","accounts":{"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f":{"address":"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f","accountProof":["0xf90211a02fd38e6a89de82781671b2e0ff817f5dc475a5ff99845d9d74e8d098ab45e8bba098b9341299bdca6c6835f4c122db9afa3265ee3f2664dfe23a5bfddc0516e8e9a07dffd5dd1af6a964c8d0f0619111798d2b6c3a330ef0972f8037e6fe1e5342f2a0cc450839cf939bd68ea207f99da50837a3aab14868b5ff47d5119cdfaa5a34e1a0597982c1927a69e262bfa7a70d7c40f73403f49d4d0d3756c67c88f332888dbea049767155cd5048ec15feac68353bc28521628e783844285e007423108dce6ceda08a16fc980ffdc5c96a8cc6ff6f4662d205f73f56f5024521f83a01619ee150a6a0c50b07405310ba736c36f50c78ff737f27b473b3b8db4003239c826f2d527d2ca0ddcbed1474abbde67cf1863f5bbb5f64bdc50333793da8284e70a58fccea9822a0e3953c5953c73111edf270e786f26b552a3785b10506b5ab1decb0128f0f62c3a0e180b459777efd3422bb762dc5330bbf56838c5fb2ec5d154634919a294ba71ba011036381cef30c376ea75e145d264c74cf16321142126ba63e378318e9872a39a02b3a80ea0573c6d94edd0e5a2b5b4f40723b2ce2b06514cc9cdd2fc3b84266d4a024f5ebadcc676da0fb1ba1f5c0673237918611d84e9d884c0523f6e1ff3c1300a0fe74540dbfbe55ff709778acefad13c9fa330f18247d28bdc25f2ce20db17762a00b6512207ffba7ef676015c6c7f55c3af634219325b8850765b6d607346da94380","0xf90211a0eeb642981ebbfea9e8d9ca8064aa8c79fba2cdf8ebdc43ea5f564b7a69a3b991a0b5c6ae63ada06d0d5ff8175d6477fb04cde10005e4903a351dd2c7597e9a7fa8a0afaccc3fcfe8266f9be1238125620d744a154ca2e25d3fdad6475241a4b2fc6fa04cb0805d8a4a82e9845fb9464b3db4dceb9de5bb342f44b991c4b30a29f936e2a0cf9c644f4958a1e6c859d23ec87b5b764567091d6a26dc56c77ab5d7073458f6a0579833e32204f41a907ac3075372853ad8e4e4f2403f0bf903f224fe705de357a0e17e48ca939d958b21da67d2ef4388e7f27ab611d0d51ecf1e06607d84ea7c05a05e8852168593269980a668e5401ac9116c8f895984247b8ccd23b00dc701132da00b1c40026c364083692bd80eb55be54815655d529b5ebee9c2a4de1c8cafc1e2a078bab4b70640ef9a7943a34a6d9a042f03f0bcc1546601957c39ef43b2802572a096e7891fe74726aef0b495a14f251feb248037822201f63b5b70c68ebda6946ba0140ed7d483b85ac60cb6afe7e61a353d3bfc9aef0e1e5c7234bdcfe0318516bda00d61c6ac83e6f47f0507e1dff480308986dfe92747dc1e08144732fda02763b7a07d6d28459eff7b551afe84605fd943889c4ca880246dc5304880937d3b78ada9a0579601d71e4f0d72e99e151ba5c74e887a8d0951f9409048c0cb0f4f15b68286a04473d79b376145c166d5ad76a57b1c20f285eb3ff1a835e20c3961d1e87e68df80","0xf90211a0cbdcfd3d0e50d87cbc2ea467b5f981e63c358eb876a54a83bc3b3423084ad3a7a008e4ee657aaed95eedcba4010a5bcf13361198151a05c6aec21646f115e3b535a0f6bac2575fd699c504240e957b3fbebcfecc87f7896f3610db423097b63fac22a04952678d4bac28ced05d7205765017a80951c0ac0dc90c2139d60aeb99831ebaa0c07eb9570a50d2368fe682497e1bb18ab5b9df93369b8cfa58033ec88608b07ca013d431c63adbacd3f8bb237ca001d365961109636a30888e27c24cd57b3708eda0c391819af1d3279f2acadd1964942ef932b71910a0451addec12add4829c024fa0872c3d033794736c2c2d2ad9eadadc1f7ec69e84f215c421e99f9a062da3812ba035272dc7ead03529043cb27c5dac00ae2f8fa446b47b087833f738d8e2d5f1e1a0ec2c1eb5e1dfa1c278577c0292247d776e34b9672feb9df10ec4e286142cf17ea0618fee05c25cf48224a64c4c152902c6a6658cc7ae58d86e56468545e4bb5af5a00786d91ffcde9662d7b509cb24856161503e00ff946bd7a724fa8cc165bb92fca025e11cbb5ded62c2601c160ea6c836e1c149c22bc870a30eff32bc2be9a88dada01e46c9179c1624f1484c87c2253feef623ff7e9491ccf7d3843311b250bd484ea0f5effe048b3008d6d7606ee8f06e5a33bad6a629c719f2129d6ea280968c41c5a01d42ff92b1401b5f0f3f6f6dce1957f82f1ae6c0fb18f831e1bfb8e1fa606e7f80","0xf90211a09d10615234b635a0770c38e4f75cd310542adec460e6e8927786cb12009f9d11a09e9553dd12cb8357ba9b0e12a7f498458ee317aa9187caeb4550e724f410531aa03f1974f7b3b01d6ad1c22a18934880d619fb6bf32ebfd4238286249fe7ad1dfca0eae53434963a104875bc808eaf6f27b65186abcaaed2535e2df054186a83c014a0ccc12f6fbab90ffb31429c2d002462a7c799b21c18c23f16d9be70f30506e181a0dae78dc4b9b3cc708a5155c51765db522ea1bd9765ee47867fd7d6927984c967a0124693473119ef0f3b2284b66d1b2ddbc828b8c708c7507360e67d4919118641a05db312d420e050452b6c4b40838fe99bc53ecfcaeaf21b09047e9a0ec0584356a0f3828990aa9cf43043b67958d09db25208fe0853b7ecc338bb21d413883fb9d6a0a0d298e88cd484f0202cb0345db3d11dfbb61e264c041bb3acae8607abd6939ca0c28dec230074086b1bdb133d4491e6851f7d6bf362391622cc63db20bf65e452a07f6c88e554489963c18db4d4b90412ad98bf17bb1634ec4c48a1b5510b8e0d09a04cef350a82644639fdd9f77841eab0704eeec29501fdb1ad463c8b701f02eb97a0575874ac578bce471f0513f7614629f2b114feb1ec7a18b757c251afb86bd7c9a0034d1aa10c94a29976cec34c79c344238d35a12e62ee4a9fa6374685cf870358a0818390e8cb814646b1cf68e7af8b049c1655da1395679ccff7710296e7799a8780","0xf90211a0f86572014cd4a607783a6f1ca4d0a64292b54d35632b81c6d11b0038cd9b071fa061af1cd602a7ba6117a19668292f03832e3ee780671b45ffb9562aade5c7e19ba0fdbc79db9b1d9177cfa1ea1f8ee874efeb246ca4595aa4b61fc450cd38ccfa5aa0ce8ffa086b0b1197df416730224678b2135d9381b846aeacba44e83bb9df6002a0c09d7eda148458e9349097f67baba21a72d889fc6fea1d43370c2460c3ae3f91a0cf691f37b7afbd977e2417c80da6cbfdb7e34cf6e2663089ebe7d4db92f5c3cca034fb45324d895cc7d52e0863a876a1c17eacecb0bd0c3f3152459f41088d787fa01afe21b721e6e28ffafe59350c903a9e73970cc96ea05e1514c84f1273151d07a0f81baa63bd7f2ca7fbea480c06845e82fce18b776336edd3d7bbb5aea5d303f0a0eb5a32c35774a397a2e097970c2af1def8775acb6a4a5219e0dd7ed3a96e7b2fa0fdda1bc5175a678f56c0d444368b69adbc4d847cbaf8cf081cea54c319e4ab1da08b82f3f4ef09937ec7588804a008af19693bff5139164514fb3ea6dd4b18d5cfa0e9a216d9f31150c5503fbfac73821dd01ef9580ed37e1844f9d3916bb7f733e3a069bb48e9322cd87baf22e5a2c90bf60f024a300fc3ddd1fc4ec35e5337050304a0e27e8aeca2faa2e2ed8fab1f6f4e0cd9d438b80d697a12170c3255af81b0523aa037fb18250d5c9a74940976aa224e08cccd1b5a283b4b2b8f1d599a14dd06395580","0xf90211a0eeca7c52bfdec01ef1a1c948406d1cd95c628a48bea99cca08570e4c48c280a0a0f1a510919c07d8539a9e7611453ac3f4b64e575355b8f0a1c58f3c54dc1531a8a05058a380b065612ea7cb9a7b45174068b6f71665fc21ebb73dafbd4570b6fa14a0684ceb97baeac2a9c3b5a14118d4f578c980acfc7189ae17541ae56e5407c2daa0dccf7318665d89412fdffaa5a6741d11b9cb529afe504f770eb6c0c748a608d3a08b71dd67c9ff6ea323b5ec1302bd2d6437816d0a68bf4b29a48e162c8c61f7efa054ee7698a2ebb6c3aee700b66eabb34e688efcc8001be7d84a75d5963acf4590a03683d52c2d25978986f9323766a8774f2513568fada5cbaf5a549e1772186709a03412ecb9bc8acdb503195da735e1ab9918d67638ce321eed7568a33f934d3677a062c5adc422d6393b0e5d69b4c313ee3cc342173e89ee610f8341aaef66b226a7a02d25b88a1116baea226ff7b3fc1cc88c2082a14b8eee6d8509dc0e24b727400ea0f2cabb17d69bfb117c719ac9c0d0d83015bb8e7ae30a468097ebf31cd09b6b43a0e6c0bdc36fe19040267d532d6dd7819b0e62ccd920550dcac631a58547e6d6b4a0399cd0904ea2242055795b194f1bff9450adc03241c9d55d8b15c322b047efd0a024b441e9cf163baf28b3771ec177c5be78292b0fef3978b9be425042b2b017aaa044d4fc328e00beaec2a5fb43b643716f646c34fe76a1eaea963eb6b4087137c480","0xf8d18080a01a27c49a5a77e292b591767f76ddf2bfbdf1752a5b53c7f07c519d0868760d2ea0ad6cb523f73649d74c1213abb948c10037a7a342ede5cd373b6060061d79faf7808080808080a0d8825f40f808fd1d368ffd5381e2926d2263bbbcee3fee5a1aa7401328da3402a02dca1cd7f04d0fd9625b649903883a2faa52ea6cfcbda738e61f6ea6322328cd80a099fec790aed90a5f7cba13d2cb2d22c79c6e737b5673133796cb831629ac3cbba0d327ffd4270f97c978c638645dc59c0a8ed42fc09bc538c9ad91eea990f543fd8080","0xf8669d3ad8a871b31cb3552080711d61fda45242133e0695c60218a95533aa2cb846f8440180a08af15fe9c3fb8fbeb9952e1f0a3ca415821af2225ba7ce0a31c2d2f85cf53a28a029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0x8af15fe9c3fb8fbeb9952e1f0a3ca415821af2225ba7ce0a31c2d2f85cf53a28","storageProof":[{"key":"0x0","value":"0x18","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf851a07857fa9fae1428bc873b55cd9278c7389972f3a3e4be1b7ec97126ded1666be9808080a0a02d6b52757f7816acf5f459d06658b3af5d944bcadceaf803769ed1ab55fe63808080808080808080808080","0xe19f3decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56318"]},{"key":"0x1","value":"0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a023d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","value":"0x2d52cf40e376d0c501b301647a7b79778e66b32a34ba27355053c342bf0ff225","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a09fe5155fcf03f486c25368e95c45d5cba7db086506a6b4f9a6bca797ebddfdd680a0c361b0facf1b56062bfe642eed1e8bd00b3e55df0f31e506b8ffbdacef26338780a09544d59ce1ced6a78e8c313ffa8a8d541462fb6d1a8b22d112a0bd39e1d20c05a0d00397e2834494f1a87bf191a87949460420888522835d3d435e06568b920e8880a0046fbc3d47f51140d92c099b92c5e03645a1740c42fc1da6458341d67fa61de68080a0adda1176b24bf54a2c0158e595ec0544e277c7673613e472c8ce783b4fadf833a0537202350296d8af166dc6d39dad42dba0bd9e4e9023cb0617de351a29a74678a0d8b3cbdfea9f1c9c18695c20ec0fcc61d720e048764997683dd061cec09b5e8f80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a02d52cf40e376d0c501b301647a7b79778e66b32a34ba27355053c342bf0ff225"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","value":"0x95254d30ee04eebe7dec826096d5ce0b635474714dcb610d3f23111f71b8a981","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a06103cd09f1acc2345cd3661cf80773fa786a58aa1000d776ba6a8d7d1fa95bfea004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a0f9c0b2156072e728e82a583460ac26e9b75f687388d79049d13a7ab29327771d80a07e91bb60abdca65a3ef360fe9bbd2fe17716bed7fa67bcd7607ca555cac1b501a0bbf80a673c67484bc593ead364b21f4789bb90e9c9d08114dfea08cb95ebd2f6a06633cf42917c5b16425df44ba19ca9ae58c1df7cd3038246724a4852e2b65996a01036b6f56d3bac8fe7ad637687eeb7ca20184b898f24678b4fa1d7745dd9660aa0558b02055c29f0b66ff195b9b9fd6234d5c97fc40584701697ac12e5e84b9452a0a2aab2c8c547a76c552e0cecbe7edb5cfee7a83866967305e1b464c8263c01cba08c1679d8cdc9ce14b68eeecf0172bed65e59f98f8bcf93021b0977f2cbb6894180a023fc3db22338cc8d6b06836e10589aff7e7f73fd8a2e17b7c8e02bca86ab075780","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a095254d30ee04eebe7dec826096d5ce0b635474714dcb610d3f23111f71b8a981"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","value":"0x39b1cdf063f1c717d4a5450f1dbbc5683dc242cc8600ad7ec5ba0f7ddff664bd","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a007c522ccc7cec8771c7e60104825e57a88fca9ef833a368cdfa592ddd17db1978080a0a3431507a80e92ed617c99a803bb36ab27f6d1085ad26fa4672ce91b5c81947ba00bb934ce449a830b198be4cc1fbb3efb43aaa12dfd15df18581e07a33fd2592da0dfec69d15bd73b0b06344b84e6e9cba847c7e2b1c2f19ea42f96563668661ca98080a0c046a31a3a76fb07795fec6bce8ee2d58d6da9e053eb196e6d99f0871dbb32c180a0d64c5137b3bf612119e481de1f286855ab03b5a89205e847295cbf7ece0943bfa0880ad135a503864e143431baf513e4da174b3827a1eea4ace002be0d4c15715aa01064dbbc60b97bb3006c07aa9e92982aac85f33b477863f2bffe3ec701fb981ea0e5e159a9aaa234f1b61d05b54844f17d3f28de3e8cbbf4f78bbe80ee5828c9e3a08ed0b40704167fb82194ea0cf45739a72b0f84f0f3e6c7be89ed220eafffd6ac8080","0xf851808080808080a04dd88bb04fac169bbf3c4a222c80b687a630117edaf83e52e13ca6cbbcefe1b980808080a0433788bc4a7a09b0d2faeb9c2d44f28b8124825722a7f23444f114f30ee369938080808080","0xf8429f3695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a039b1cdf063f1c717d4a5450f1dbbc5683dc242cc8600ad7ec5ba0f7ddff664bd"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","value":"0xfb788431a92e686f4d81f0767215180c693f398d464eb15bbbeacba887ff5db8","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf8518080a09dc15af3498df1c32e3d7bf390b3ca1fe13468962f67892a7346bf05e69c259c80808080a085fb7cc7bd0c5453a3fd70edcd8bf776001862e836f68f5711ed83016563a933808080808080808080","0xf8429f357165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a0fb788431a92e686f4d81f0767215180c693f398d464eb15bbbeacba887ff5db8"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","value":"0x5c257dc4db482d47e778a821c16a0e40b2db88ad472d1bae1730e1906ea912a8","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a09fe5155fcf03f486c25368e95c45d5cba7db086506a6b4f9a6bca797ebddfdd680a0c361b0facf1b56062bfe642eed1e8bd00b3e55df0f31e506b8ffbdacef26338780a09544d59ce1ced6a78e8c313ffa8a8d541462fb6d1a8b22d112a0bd39e1d20c05a0d00397e2834494f1a87bf191a87949460420888522835d3d435e06568b920e8880a0046fbc3d47f51140d92c099b92c5e03645a1740c42fc1da6458341d67fa61de68080a0adda1176b24bf54a2c0158e595ec0544e277c7673613e472c8ce783b4fadf833a0537202350296d8af166dc6d39dad42dba0bd9e4e9023cb0617de351a29a74678a0d8b3cbdfea9f1c9c18695c20ec0fcc61d720e048764997683dd061cec09b5e8f80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf87180808080a0cd681671de7469b3b477af0cf6d21ac8ac1ffdb00023d61b2a0d32bd577e4afd8080808080808080a0c64042becd2253a1dda3bcce4a06612ec632aeb61e84bef3170dee942811ee62a06553bc31e3c595f52fdba16b48dd7cac5c3046823357c3140edd803a7090c03b8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a05c257dc4db482d47e778a821c16a0e40b2db88ad472d1bae1730e1906ea912a8"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580","value":"0xa78b8e772e2235c3777d75526957ecb08bb0681b47f5ac2582bf0add4c004185","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf8518080a0cddb6195608409ce1e3af7bcafb1438332c340b7ca526661a0cff52f7acab826808080808080a09a1a77e2ad05e8178da178bf660822cefdb0572bf5dd9dfda7caa1266003d84a80808080808080","0xf8429f3f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cea1a0a78b8e772e2235c3777d75526957ecb08bb0681b47f5ac2582bf0add4c004185"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585","value":"0xdc923d47f18818a25c44302ef12ab6cbf51354749df66dbf1676622737c3d6dd","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a06103cd09f1acc2345cd3661cf80773fa786a58aa1000d776ba6a8d7d1fa95bfea004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a0f9c0b2156072e728e82a583460ac26e9b75f687388d79049d13a7ab29327771d80a07e91bb60abdca65a3ef360fe9bbd2fe17716bed7fa67bcd7607ca555cac1b501a0bbf80a673c67484bc593ead364b21f4789bb90e9c9d08114dfea08cb95ebd2f6a06633cf42917c5b16425df44ba19ca9ae58c1df7cd3038246724a4852e2b65996a01036b6f56d3bac8fe7ad637687eeb7ca20184b898f24678b4fa1d7745dd9660aa0558b02055c29f0b66ff195b9b9fd6234d5c97fc40584701697ac12e5e84b9452a0a2aab2c8c547a76c552e0cecbe7edb5cfee7a83866967305e1b464c8263c01cba08c1679d8cdc9ce14b68eeecf0172bed65e59f98f8bcf93021b0977f2cbb6894180a023fc3db22338cc8d6b06836e10589aff7e7f73fd8a2e17b7c8e02bca86ab075780","0xf843a0207c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422ca1a0dc923d47f18818a25c44302ef12ab6cbf51354749df66dbf1676622737c3d6dd"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58a","value":"0x28240fd8b95647d56a04b62c86bc4e5a78203ff5c3393fe86482de080d0e90a6","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a0c10be40210eaeafb7affb37be1cf73a8d79ab6fa11811f92ef9b383b5c28ec3c80a0268940e99b915692f0d70fc16d7913eb67200da8170a5246eccc8e99413e35f080a0dc430d4af5cd2ee1b45c3ccbd3dd056d439593455787b501d60329693c1960e2a017e5b7ec0b1e27255728acb3ba13a3a7d97db3543a86e26f020e7314fce5af3e80808080a0ce1e04072f90d7a1e3da7fa8f38a01770f4f3f42283c600ae9b823b8e5353a31a00d53f5d0ae5101da621781caa1e7ea976fc73e36bc4c0024aea79f92384904d5a0424a41de56b820d7c5bd231be063b86a6f94a67a7aec4b592b37abe768886ca280a0d370dc8aa939bf4b8b29d1cee7ba493bc77f9b1e876133880c080bb0c8353aa08080","0xf8b180a018235be78684e641db774248330c6d069c014248394e2e05d8ef170a3430bf9aa0d015c8e57b24dbee103560df45cfd8362e487b63c8dd8bb0d9067b17b2a322a7a0f0cbfe7fa273cfbbcfa9c3439d44db08d99b6f8c511c84a9e0bde7a10c2f34248080a008a98a5e6c395d0392a114ce84d56d94fa31649c4b81ae9d544db634674fbfd980808080a099b1d48d6d8d9ccb1a75e184ea5e013e7cf5c7c5ff1edd72a0a343bb44c231db8080808080","0xe216a0047ac7de0d120fd6480927bfd9740c37ed9e6b562a9190b9e6f6f3a6dd120c34","0xf851808080808080808080a0fe9a758713c23aa4184f64c749e72340046c9bbeda80b5232df250e76f1d35c68080808080a0d1d8219af8b8ac923c57c310ff1d1c21b53e47b06592d6d529261f0abe70819a80","0xf8419e3ad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de35a1a028240fd8b95647d56a04b62c86bc4e5a78203ff5c3393fe86482de080d0e90a6"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f","value":"0xcd9a4109290d0a69d874b9df41f1119ea0a89a074ed4facdef23938856ad21","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a073311ca6ca74da12c2929d6b0147d44648daf9ad644a5a8a44d105596d0b7ee1a0e7118dcc330222388627232176de8a6aeac25659a21c504c32ba0b54c545ef6780808080a0f1e1e6a1963da281b65e26a5237bce3fd09b9c9a1f0e7ddff218b7e53161b360a0c96daf77227406fb0998d1457ac161698cc241a109052a82a74db1315d936c2b80a083c7d6321385cf0b373c8867bfaf9ef73a28c19f5a5c285df71f5aacdbde76a3a0f6b561dc7ab1c1be3744ff2503d569d967e4f0db47300ecb9515cfffcdd39481a09f5cede4690b5ffc688db0d5bb176bd7b95b0e8247bc23248485c649f581e47da01ca0374b90719499783a9848bd1f9a903144d40c02c73612041ee835940b421ba0dac9b3d0a1b0305873a97e2fb7542240bbac4aaec608f612022c8cb3fde00c2680a0dfa0d96c7762498735ac486aabe3df2b014a150161dbe5e6356dc548500deb2a80","0xf842a0205143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca5a09fcd9a4109290d0a69d874b9df41f1119ea0a89a074ed4facdef23938856ad21"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594","value":"0x32800a926a5b9a99a6d483c673abde97967bc214e83b82f1fb9cb4068c72474f","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0c5c4d600e8237c5f052e7a4fc9aec09c22884401dec59443694deb4b9418324780a02a6f27850ba820ca67089d13837414acd6bbc1acc82e094f45fa1c2c00406eed8080a0e2a57e168b71096b928357bb9350ebc53dc31ecea2cbe5f6eeda70ee63e7feeea0bb0c8623a00fbe57b61cbf26a353088a0d5c78bca40e81697579b59416e5cac1a023cf38f358412e2975c90da2a25647a4739ea853ce1c178e05b9e8d5bc07d51ea05100b51ce8cf50451300450adcdbb8eebe935afa2b283e69a4a48ac80ef45c7ba0e3b3cd35c91710546ba23f317d666e416ce399489c752a0e59f58b7a9d23a41180a0a7df0f5c2008e7b9cd9daac967ee2823014f018659a4e0162e2a6616752fd4eca02198ceee682380630891777c2babb47f07b64905de79a141bf2d5fd66f9dec4b80a01b504d2406463a849075d4593790e6700b882f94adfe6cf23bc7f5b7345ef30180","0xf85180808080808080a004420e11ae357a6902c99daad0cb70dde57bd374f6d2d4804d3e2dd70180a63b80808080808080a0b2b3100e55edcdd3c5a8998b2a73751b4353fb1ab58bd79d8e96550aaa8f552980","0xf8429f396013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d691a1a032800a926a5b9a99a6d483c673abde97967bc214e83b82f1fb9cb4068c72474f"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e599","value":"0x42090ce68c0a1f87e43c254619b2818034ab8e4cf395eeaea5894d969b4f852e","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf851808080a0899e4eb360e9d5d048b1c081bbea9035ae1bf6a1bd79797cfd951424825a79a38080808080808080808080a08987b897c62c87bf86cd5e9f7f64cc1844242afb9a52032b327ac1df191eec0380","0xf8429f333a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acf9a1a042090ce68c0a1f87e43c254619b2818034ab8e4cf395eeaea5894d969b4f852e"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e","value":"0x5966504cbcd3907f9c58424ea70d925a5734fb7dc0204888795ba5a81f363c45","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a0c10be40210eaeafb7affb37be1cf73a8d79ab6fa11811f92ef9b383b5c28ec3c80a0268940e99b915692f0d70fc16d7913eb67200da8170a5246eccc8e99413e35f080a0dc430d4af5cd2ee1b45c3ccbd3dd056d439593455787b501d60329693c1960e2a017e5b7ec0b1e27255728acb3ba13a3a7d97db3543a86e26f020e7314fce5af3e80808080a0ce1e04072f90d7a1e3da7fa8f38a01770f4f3f42283c600ae9b823b8e5353a31a00d53f5d0ae5101da621781caa1e7ea976fc73e36bc4c0024aea79f92384904d5a0424a41de56b820d7c5bd231be063b86a6f94a67a7aec4b592b37abe768886ca280a0d370dc8aa939bf4b8b29d1cee7ba493bc77f9b1e876133880c080bb0c8353aa08080","0xf8b180a018235be78684e641db774248330c6d069c014248394e2e05d8ef170a3430bf9aa0d015c8e57b24dbee103560df45cfd8362e487b63c8dd8bb0d9067b17b2a322a7a0f0cbfe7fa273cfbbcfa9c3439d44db08d99b6f8c511c84a9e0bde7a10c2f34248080a008a98a5e6c395d0392a114ce84d56d94fa31649c4b81ae9d544db634674fbfd980808080a099b1d48d6d8d9ccb1a75e184ea5e013e7cf5c7c5ff1edd72a0a343bb44c231db8080808080","0xf8429f33044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b56a1a05966504cbcd3907f9c58424ea70d925a5734fb7dc0204888795ba5a81f363c45"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a3","value":"0x173381a2ce0b5e7ae9b08055980d8cd5caf104a702cc63d297c2077504df2e82","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a08a370475f78ee1bc03580b2b2e9b16b1eb452f81212a9d8127d954e92fcc8fb1a0c1bb8ecd59b80bbed441ee18ebdf94811827f628bdb0bedb6ead37e24c92a95c80a04c7fc64651499fafd4cfc77092da4144ae626a73550cfdec5930df2634af02c280a0e0a013bcad6a578658f28a4049f44e162dfe682797a6c9a5244345a02ae649178080a07ce04089b42c54d91d5b5f41b630a99a7661d48d1bc0c39a4857180f7a418fd7a0729f553b90c8aa218b3b985df9d1ff27e0a6711f1468b0c6999f1a92bd2ac070a096be06c6c4b4ef62086038abdf758a47ab47d0f88f1c8d45ffa06ba2d1fecea88080a066869a20a67748f29010705a43fb0cd62813f7b0090eb66250ae7c8666fb4c26a024c22df91486e78fda115ca5ca3607933ff5b04d7c2977621c24f05f7d3ec44ba010a870fe4501d8e2f800e4d73623d069988e94ee790123f209e3d7f425534eab80","0xf843a0205b1bcd89d0167783ef3c9078f5aba26b1dca729632fdede82297d26b9ef672a1a0173381a2ce0b5e7ae9b08055980d8cd5caf104a702cc63d297c2077504df2e82"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a8","value":"0xcd89dedb22833e4a192180bbdd2d0886030c067c6e22921bb39104cf62831f03","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf843a020c483131d4db389081b171cc303f3a6b15777cc81e0f66f0a8c82d85c6afc49a1a0cd89dedb22833e4a192180bbdd2d0886030c067c6e22921bb39104cf62831f03"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ad","value":"0xff04decb90109c6941ab76457d0449c666f996c430e546e6c0655aa986d621e7","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf8718080a0c3e6f2dca6ca60e59ec4f46d3d3d49f73831e6b2d122d6748f39b52db95a51ed80808080808080a0a32a488bdfb8c49ebb54e1e35b317b2e2abf2b0dc9f787d1b43004c8593d691180808080a074957c7f195e2392b3a02f0652ad9c11ff09bda6aea34ffa6d9d0eb44605b54c80","0xf8429f3c2fb1c8a64dd0ef4342f68885ab9cf9863beb0f01cdd1a8b305cf747368dea1a0ff04decb90109c6941ab76457d0449c666f996c430e546e6c0655aa986d621e7"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b2","value":"0xfd2c0697de5cd00ef86910c06ae2bf47697564816ece583c6c3d70bed9c17ffc","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0bdffcee71e093972beed24f272c1c141161690138d7e3b6aaaf19489355d6e548080a0554c5f473bb32eea8645636e6b9ada3625008e956f75891c946eed555f608a1ba011585654818deb63d9a08c124a0245dc2a9b457323a521420cf9dfecd1222cd58080a02c4cb2a2fefc5b225a10bd717ff7fd225ea362dc5eaa71091b6fca5f3ee9d19b80a03e4c86cc1f186bfcc333af8847ecb8e8e0607172537fab56ec62e17495a7748fa005de0aa6773a0b4d51716a986ed7631a65f256a02f3f6b529d9ab0f713138890a0972bd683b0bdf4d1383e11b0bea7b23c0d92409b48c540367335c6f371033908a063f6fc4a406b7bb140217ed6520b603ba669f17cffbb76886e88e22b241a51dda0587d72713f85edbd55ff0def84b82bab4531368cd2050deff0e360c22a3ef9c3a0234ce860f0df77a2a1cbda27ef75fdd13977debe9955742cd50a1e426ec5473180","0xf843a0207c993cb9ca55cb4f25d3214b28e970d532ed00e7124447c6da58966abf59e5a1a0fd2c0697de5cd00ef86910c06ae2bf47697564816ece583c6c3d70bed9c17ffc"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b7","value":"0x3038277c5c0507dda59579d580e57e020f580002b2a22b7b91ca65d1c7aa979d","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a057f54bb76bf601b1a8d3be95c811096f5cc05787b74e9b398915b646d6cc93cba083a1650ede482514d207120e4f12614dd60ddd2c078dd92bafe58b412c08200880a0653b618d408054a81ab50663eb4010377d1d5fad5aa003c3c7edada1280ff19b80a0b7490a2e96e69005de53df486532f9752e56ae7ac3139ff149a5c0dbe83571728080a02c4c3e10fe960e892a34daa718b69dcfe4aeffa65dd3cd930a0b762f7b9a81248080a0bed38aa7ff016abfc4b28a740eca1f26d4cd53e43f80ffb14fd38983ad41f37ba06d39d773924b6912477395d27b3484e97e4deb16e78e3bac59c94cb6ca8a10c88080a0674867e8bede0a3f6391aa87fbb2c06fcbb80a9c212ee57c34e455064ee3b38780","0xf843a02037c1cdf00f527d465e035eb85038ec025421aafa09c17728cdef4c0319f3a6a1a03038277c5c0507dda59579d580e57e020f580002b2a22b7b91ca65d1c7aa979d"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bc","value":"0x4ecd9372b3d3b7db017cc21d0e754aa938b0503b3ec62c3b185f28e642ff8efe","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf85180a033e335fdda5867c48e7176f889fd7e279ea732ec1d76ca319bc12bb3ac87dbc8808080808080808080808080a07c1f795f905ad3d54ffec5c4d1e5ad7023b74ebc39a3770e196bb286be7f74388080","0xf8429f3414becb71a9e265bbf779d5dab884471ab07491acc55da004865722dd9555a1a04ecd9372b3d3b7db017cc21d0e754aa938b0503b3ec62c3b185f28e642ff8efe"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c1","value":"0x56a1a001b6ac8efe113db6f9997650234e253012fc29ac138ea88c7bbc49ab7f","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a0e6ea1e436f05d24ac984b6d75fe4246a9abe453816406276c3dcbdf80aad793780a03fd646fdd60bafca2096ccbcdda65a7e483305274e3acef764f2643ac0f7cf4580a016d82c45afb190bbe73c553fa3e9821e6faf80178822629e44966602d77405d6a0e616d9d455b9c021ef5f994756cf8ddaaa914f4a01e67a6f709f6cbe40e2d1b5a0ac90db5c3bf7cebb036347ff37ee28ef741711f3deabc288b32be6774fd7846e808080a0f151043c33fd525061b5093bfa289c69b2e3e6d307346e9d1f8b27daf02e4639a03a517a79284f29916504e8c87b0d255594e9555472c3c5506b57c52a5ceac94fa05ae394240a0179fd6098f01bbb050ff08fb0434f03d322063f0f7675b020664680a0468171e6f3b407f9a89fb7a40fd580f7c4f6a7183fcfe57d4a0737c9e287c5e78080","0xf851a03a237803b2f954e84d1672d67c63fc386beab8ad6a39c969992dfdbaa7db20b4a06dfc98e7ea0bae439ec4a91accf600766abceac32c27e75b9bc0299142a9a952808080808080808080808080808080","0xf851a0c347cda866a395df2f0008995d90a0944f9b00181ec017bae9946945f83e0ca28080808080a0b25c8fe5663d6223e681dd230052cff9714aba76bb351cefd62716916670254280808080808080808080","0xf8429f2049a1b7f41c7253d14878e9f3078f7c30bdaf197b7843b5e995f3205b52eaa1a056a1a001b6ac8efe113db6f9997650234e253012fc29ac138ea88c7bbc49ab7f"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c6","value":"0x805e8f379e8c46ff832bc1de4c18dbdd4298af7980a2baa510f08bf6b535102","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf85180a033e335fdda5867c48e7176f889fd7e279ea732ec1d76ca319bc12bb3ac87dbc8808080808080808080808080a07c1f795f905ad3d54ffec5c4d1e5ad7023b74ebc39a3770e196bb286be7f74388080","0xf8429f3ebecf4879f2388cfb4eef3fa5b2610d4742229a536a7abf3fd78b590e515ca1a00805e8f379e8c46ff832bc1de4c18dbdd4298af7980a2baa510f08bf6b535102"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cb","value":"0xff217f671595e9442df0d21b483dbde49c2c6eb26a7552e0895093f6785299d0","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf8518080a0e140d1028a275a6d0769bc27299ebbe580d038a5d9ce720c31089a322da4965480808080a0e4373dc598c156d176309d2a09ebada130fda4c55acb3cde0edb631a5ea73ff7808080808080808080","0xf8518080808080a017be900871218000002e77f12142845ac02e201f0ca9b9de5d887d90d44c6def808080808080808080a0d959ac4a10a578c1773a4356347b2703bcd03bf7cfdb3b7a0fcc7ad0768b8b0080","0xf8429f20c650d451c01266e75135d143f261a021319a4860f12f807e625d9a446910a1a0ff217f671595e9442df0d21b483dbde49c2c6eb26a7552e0895093f6785299d0"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d0","value":"0xa14093e2f3dd910e6264c01acb8fb0c13b120a7fb5ffd97781ba06b6679d2bf6","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a05db83fdd81f6090f694fe376efd65a0cd12b8b860c73c61b62b309c9117ad8e4a05f488251881619100ce873df1b38463a17d107cb0599e2307806e3024ff2de7ea005e52ae30aa266f969b979acc16fd19e9d95385ded961073736d07301a207a9880a03e33b2fc18f6c4f004ab8045d8208fbcabf814590732f72fdd512539c4a39723a02a12b79deae8f4815b15d19f3fe7209b828739dfecaebd686929a5a3e546c30d80a003301dd18ff8a58b9744d88c0efe2dd68294b19387243bccf37e07b7e82600f5a00bc21c893de4da817fb01762e853c315804f8b9c6be34e513110d10aecdae65aa083a890a2b7928642bc990d01100602473dbc6c93bb220a60dc063bf6590473a18080a0f302ac97324252fe1d0ce29e5ffdf3c20e1ba5b58706c922e39b381560912010a0c268b1f0ba065e0715e965a2a88d47b4e5613bb8811b13d87793fb5d0f833422a09506a8434b8d54272c88db5524fffe98ea3a3319d79daa813ae766bb20e9436980","0xf843a02055fb40d3c79c636ae8a87d67d6156ebb0093442a7ba8c3574a9ff1683c5901a1a0a14093e2f3dd910e6264c01acb8fb0c13b120a7fb5ffd97781ba06b6679d2bf6"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d5","value":"0x96c7f94de6cbdcfc22707452e5d1db3d931d9dd5e9606d76001ee471f2749911","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf851808080a0899e4eb360e9d5d048b1c081bbea9035ae1bf6a1bd79797cfd951424825a79a38080808080808080808080a08987b897c62c87bf86cd5e9f7f64cc1844242afb9a52032b327ac1df191eec0380","0xf8429f3d6e65807074f2c436e5186a2d89868587438e310ebcb745d33740f512e150a1a096c7f94de6cbdcfc22707452e5d1db3d931d9dd5e9606d76001ee471f2749911"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5da","value":"0xc371c32a765085f87dcc307150f0fd146419ce9afddd9bf940a035223c280e23","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0bdffcee71e093972beed24f272c1c141161690138d7e3b6aaaf19489355d6e548080a0554c5f473bb32eea8645636e6b9ada3625008e956f75891c946eed555f608a1ba011585654818deb63d9a08c124a0245dc2a9b457323a521420cf9dfecd1222cd58080a02c4cb2a2fefc5b225a10bd717ff7fd225ea362dc5eaa71091b6fca5f3ee9d19b80a03e4c86cc1f186bfcc333af8847ecb8e8e0607172537fab56ec62e17495a7748fa005de0aa6773a0b4d51716a986ed7631a65f256a02f3f6b529d9ab0f713138890a0972bd683b0bdf4d1383e11b0bea7b23c0d92409b48c540367335c6f371033908a063f6fc4a406b7bb140217ed6520b603ba669f17cffbb76886e88e22b241a51dda0587d72713f85edbd55ff0def84b82bab4531368cd2050deff0e360c22a3ef9c3a0234ce860f0df77a2a1cbda27ef75fdd13977debe9955742cd50a1e426ec5473180","0xf843a0206694f21c46735727f9aedd8541e81c27d760e39807330e4846d12048d0ca7aa1a0c371c32a765085f87dcc307150f0fd146419ce9afddd9bf940a035223c280e23"]}]}},"signatures":[{"blockHash":"0x35ab50ca64a30297cb6d1426dea91623138bca3a3ada102d7ba6a7e2fb2245d8","block":9935386,"r":"0x617066df3ddfc1cc1dce6133116d83396e2910a42d57c2f15aa474ac32dcd6c2","s":"0x5e7341034aa1aa93dcb7b6fb8c3216a816b52e5639f688123b54160bc6efce1d","v":27,"msgHash":"0x3c282ca68e5feefca8b6573568b5e1190f1b773b8d9aabc97f9ff85292090388"},{"blockHash":"0x35ab50ca64a30297cb6d1426dea91623138bca3a3ada102d7ba6a7e2fb2245d8","block":9935386,"r":"0x92945bc218f8cf7aa53c29b5e948ef492f5dd51773c2820f5ada34b38fe9044f","s":"0x6a6b3076df6b9c677a8eef58bcb4dff86c2817196021b51c480000b2b16261d5","v":27,"msgHash":"0x3c282ca68e5feefca8b6573568b5e1190f1b773b8d9aabc97f9ff85292090388"}]}}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/mainnet/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0xe043da617250000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224418,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x1be4f459be890000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224531,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x45871874b4b50000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224604,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x8aeaa9f6f9a90000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224650,"weight":2000},{"url":"https://in3-v2.slock.it/mainnet/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x115b1ccfb83910000","props":"0x6000001dd","timeout":3456000,"registerTime":1576224948,"weight":2000},{"url":"http://eth-mainnet-01.incubed-node.de:8500","address":"0xe9a1f583c6591566b0cda30dd2a647126d1ce0c2","index":5,"deposit":"0x3782dace9d90000","props":"0x6000001dd","timeout":3456000,"registerTime":1578987329,"weight":2000},{"url":"https://in3-node-1.keil-connect.com","address":"0xcff39dbe511bcf14b65e4030b3d8700e0ed67cea","index":6,"deposit":"0x16345785d8a0000","props":"0x1f0e0000000a","timeout":3456000,"registerTime":1578988306,"weight":1},{"url":"https://in3-node-from.space","address":"0x792cc04f89b012ac1f98c19b7281fbda8a3e1a92","index":7,"deposit":"0x2386f26fc10000","props":"0xa000001d9","timeout":3456000,"registerTime":1579088618,"weight":1},{"url":"https://in3.iotenabler.com","address":"0xb8cf3f02c24ca897b157a34019711679c6e556a8","index":8,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579092616,"weight":1},{"url":"https://incubed.online","address":"0x77a4a0e80d7786dec85e3087cc1c6ac3802af9cd","index":9,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579247282,"weight":2000},{"url":"https://in3.indenwolken.tech","address":"0x591761898ba2dfcf3b230bd3ab7d0de0c4ef168f","index":10,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579252398,"weight":2000},{"url":"https://in3-g.open-dna.de","address":"0x0cea2ff03adcfa047e8f54f98d41d9147c3ccd4d","index":11,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579267585,"weight":2000},{"url":"https://in3.fri3dman.com","address":"0xb451c4b6bdfbc4123fdd7cf61fd9dc0a88021f65","index":12,"deposit":"0x2386f26fc10000","props":"0xa000001f9","timeout":3456000,"registerTime":1579352283,"weight":1},{"url":"https://in3-parity.iotenabler.com/","address":"0x4323d321a39ed4a197524c6acd18c072f753c1b0","index":13,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579525922,"weight":1},{"url":"https://in3-geth.iotenabler.com/","address":"0x8db016dbdc03e76990adda627aab64db8106be4b","index":14,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579526954,"weight":1},{"url":"https://in3-infura.iotenabler.com/","address":"0x19580b648bb23163136b583ff5f56657fffb6610","index":15,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579530461,"weight":1},{"url":"https://in3no.de","address":"0x65b9464bc41dc35534f8b6ea5108f4905161efd2","index":16,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579538640,"weight":1},{"url":"https://letsincubed.com","address":"0x1389e3b68bbef358e4ee6fabf94d3c884deda376","index":17,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579539143,"weight":1},{"url":"https://in3node.com","address":"0x00a329c0648769a73afac7f9381e08fb43dbea72","index":18,"deposit":"0x2386f26fc10000","props":"0xf000001d9","timeout":3456000,"registerTime":1579600645,"weight":2000},{"url":"https://chaind.de/eth/mainnet1","address":"0xccd12a2222995e62eca64426989c2688d828aa47","index":19,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579646966,"weight":1},{"url":"https://in3.tuc47.xyz","address":"0x6d172460c0303736c2fd4a329664fe03c2f09512","index":20,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1579717924,"weight":1},{"url":"https://in3.ahnenposter.de","address":"0x6e314c4c7b5ae5c6f49aea2d90a1d083abab045d","index":21,"deposit":"0x2386f26fc10000","props":"0x6000001d9","timeout":3456000,"registerTime":1579764858,"weight":2000},{"url":"https://in3.themysteriousclown.com","address":"0xdaaf752eabf0dc0e8b0ef00045efed6cfda727d6","index":22,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1580328209,"weight":2000},{"url":"https://0001.mainnet.in3.anyblock.tools","address":"0x510ee7f6f198e018e3529164da2473a96eeb3dc8","index":23,"deposit":"0x2386f26fc10000","props":"0xa000001d1","timeout":3456000,"registerTime":1580901801,"weight":1}],"contract":"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f","registryId":"0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb","lastBlockNumber":9935255,"totalServers":24},"jsonrpc":"2.0","in3":{"execTime":135,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90215a06d757895a274fcffb2ffb528a2a86c5c6874af300b3a6420ca3980ab55e44c74a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca098405d9abc2e85b693a5d98f6c3f3d3cb32990e488ec42d8b6a28e89b6b25e09a044701a6962708e9f8fc461b57c13ad6f221e424065f6c58c33951e10c010e8e6a0d9c102113d82d093045dc46ac32f94da34893d26ef91e9c8cd59288383b02408b9010004250ed130022808d04024806700036c482830211090c0580400888178000d20848410074800a91000040120918203550002a440010407c920a030a0207a902c58000012c20d21403c05c44a4200c0862020ae000600226442c041a20600331a74d00404022015034081b3009866892048301420043c04004022041220201c830181091e8aa00002200c02018841569894001c415961190240172004013c08cf823e580981003111134117872871c140810c0010a8e24002020670011e0004c0828b002620f0100380921015080220202e025262018840208032004410446100a098606081a0145204210014c438414000280060cff001c2800500485000289e8707e96a381826a2839799978398832b83987d31845ea2dd3b94737061726b706f6f6c2d6574682d636e2d687a34a0bbbde173954a225e64b140a099ee63cc33775079ae5896903ef162dcdaaa9c548817cc9fa80467c357","accounts":{"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f":{"address":"0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f","accountProof":["0xf90211a00d837514c34b56d11e81a485052547bc88ee896b78038cef71e464477aaf7bcaa0f065047c2e170d7588ae6a69e0bb93daf230e47b7a2c7b2d0cc68289d3b6af44a0a1faaf76e7354957c1dc8a617f5130a51c7909440ea24a01c04ba1683dd45d94a0021f07de6b9f256cbaf408914799581f368c655dc0d937906ed2793b056862bfa00bff38241a4bd393073aa766c55801f9835c51ec68a59cbdf98886fdeda0cc50a07f55bb53616608e98861bf00afed84f7eba214ff5cda2acfe9b3641816bfa0ada0d2711a9cab3ba5b06066de557c6d6c703633d05babbb3cc557b8dd4386921c74a0268dc6e3146f802852509fc7c8d5515c721cfa1508fbc95a42bc25f7151878c4a029f0e47ba04fc52703ae753602f4f6b79052afb7c808cd40417097e33bbe1d02a0f6005570bd5861ac1073c9ebc6571265ac5572db140a72d3c229ef9cbef4e863a0ccc521ba4b9a227ee36bc9fc7bba5077e1d0b5c603669d0c61a764278e8eece2a09f1ae1e2ba090ee128b03a8485a50fa11bce6ec49b66f01d8281b635ae4bccaba06601c62a45a3558cdf183591d4d699b88ca131fa0ed86f7e2e6db526ff864a57a04c0c90e0352dcd5b35f6735193301a65d02f104155012c8e15fa19f9928cedbda0e5ce3a3a2f5246231d8884ad3eafef2b7569a5bb192d66ed44796a6ce7bf90aea091742b2aed66c73c60ef5707533a72fa6d9c4242c94e9bd9ad9891ffb2b0126a80","0xf90211a0ed61107e8e2da0be6f960393c688e533583ca8f3a2a7f68f007a955fdc0ee68ea0fb255ca9238c25704d2cb0eb8547c1a64701eefcbe3a30f6444a1b65dfc40efca023edc60bb8077b328d7547817d22b121d3f3ae8f1fcfa51af040e257fcce2613a03b8c8d8ae77522b7523717b94732b2a5c4cffbce8bfdf50d3bd58a999b2e9fb3a022760fed6d8772b43ebf09d21c2bedf728adf9f8bc277bc5da8b194ba3f6139ca09c7e8272fef3a6793ac1cd46bcb2ede36b2420ff60f8ce603f3c463946e6d18ca0db7d3042b6886a0edc59228424f2e174e36604a37066a23bf12e117236796acfa09c69ed674471f8d045fcc5edfa879f675cd5466dd7656579fc09d44511a94bdea02809cc0c667dbccc6d1b7fe82b841874e699db344624511abbc27a5174af6ec2a0f8c661771b78de8dce5d1f1932a54b79e79c6781826f80220e87eedda5795b3fa07f37834812efdec19223b45c7623fcf2cf7044da6eb45063e6282dae1bde23a7a0495239a2e05e6141a9cd41441e069a91c81708957dca55fd09aa3a5cfac83cd7a0543b7e855c3ecb74656d3bdaab83e051230f6a630c31ae21b7d048d7e45ecf43a0fa2b208be9c2041938f59cb307590afee5c0e81c2ebd046eeecb5d7685ee2179a015d0a5f0b263743b2a4df13e33d8120146dc83ffeae1ccf072f8e75a6ddac262a00a505ab4c2d9a99647a7f8cc975c255fd8516da1b618fefcea5e61029e59018d80","0xf90211a043d6827d1fa69ad5f2881463733b5b37cc4c18b9dbc731d0e9ffcd415addf1a0a0fdb98b15b6be795e5f205eb9754fd4b633f2bc6be91a247837e6a3c650fc3c57a092fbdf87c62c4a074810d85f001d7de611ba34e1254f83fd681fd49cda08d713a08fb98236b0cb6776a48e0cc0e88b42fdf1572adfab12032969e656cb522d3a7ca003b1675eb7311266746319b5b194c7df9a0265b38ecfc7db7bf3168cfe70db9da0ca2c538d00d9b9807e4deffceef845d7f7880a9ed34ba63107296fb35b131c76a044fa348291f5193f35e91260f12b8f1d0a32e13c33056cc9745ae42511e39119a0cd7497812de420c5d20bc1f6088f3f3a6696a7fe8cfae2755306d95b190a69eda09ea5238945998842b64a0623154a290e3a0258ce8ffda24fbfc0d169939394f8a0d9e4903c5f0bc5f078b388f68da93014ba5ce1b7f16b39014b4a405693159817a06370d1b111bcb28497664ffb395b644ea5a9b30987e08cabed9765cf6d494d4fa07cac4fe079e2e99c9301c6215bf6eb7957d500563d1a5613b39b4dcaf16aab73a046d643e70f23a9acd2039355df9f12b0cea9e57c789c0cfbfd6db87b223da16ea01430c956323afebc488df76c883a10ed64b3df297bd5fb52ad6355e048e9d79aa0a5e9d7978ecd33677592eec30a54c66a4db0a756bcaec5fc81959658a52b9f49a00ce48ad7800d6cb25692dbc51268a9f5b33a5a536372ab64cdcd8fed51d4c3a980","0xf90211a09d10615234b635a0770c38e4f75cd310542adec460e6e8927786cb12009f9d11a01b779d82e8c1600e3ac2ed0b5f0d70f076396a86fb6b1ea01449de00950e4e15a03f1974f7b3b01d6ad1c22a18934880d619fb6bf32ebfd4238286249fe7ad1dfca0eae53434963a104875bc808eaf6f27b65186abcaaed2535e2df054186a83c014a0ccc12f6fbab90ffb31429c2d002462a7c799b21c18c23f16d9be70f30506e181a0dae78dc4b9b3cc708a5155c51765db522ea1bd9765ee47867fd7d6927984c967a0124693473119ef0f3b2284b66d1b2ddbc828b8c708c7507360e67d4919118641a05db312d420e050452b6c4b40838fe99bc53ecfcaeaf21b09047e9a0ec0584356a0f3828990aa9cf43043b67958d09db25208fe0853b7ecc338bb21d413883fb9d6a0244d0ea1fdff8e0aad4dc4a797f3b7411e13ee42e0f7f1ad209e6730bde5ab7fa0c28dec230074086b1bdb133d4491e6851f7d6bf362391622cc63db20bf65e452a07f6c88e554489963c18db4d4b90412ad98bf17bb1634ec4c48a1b5510b8e0d09a04cef350a82644639fdd9f77841eab0704eeec29501fdb1ad463c8b701f02eb97a0575874ac578bce471f0513f7614629f2b114feb1ec7a18b757c251afb86bd7c9a0034d1aa10c94a29976cec34c79c344238d35a12e62ee4a9fa6374685cf870358a0818390e8cb814646b1cf68e7af8b049c1655da1395679ccff7710296e7799a8780","0xf90211a0f86572014cd4a607783a6f1ca4d0a64292b54d35632b81c6d11b0038cd9b071fa061af1cd602a7ba6117a19668292f03832e3ee780671b45ffb9562aade5c7e19ba0fdbc79db9b1d9177cfa1ea1f8ee874efeb246ca4595aa4b61fc450cd38ccfa5aa0ce8ffa086b0b1197df416730224678b2135d9381b846aeacba44e83bb9df6002a0c09d7eda148458e9349097f67baba21a72d889fc6fea1d43370c2460c3ae3f91a0cf691f37b7afbd977e2417c80da6cbfdb7e34cf6e2663089ebe7d4db92f5c3cca034fb45324d895cc7d52e0863a876a1c17eacecb0bd0c3f3152459f41088d787fa01afe21b721e6e28ffafe59350c903a9e73970cc96ea05e1514c84f1273151d07a0f81baa63bd7f2ca7fbea480c06845e82fce18b776336edd3d7bbb5aea5d303f0a0eb5a32c35774a397a2e097970c2af1def8775acb6a4a5219e0dd7ed3a96e7b2fa0fdda1bc5175a678f56c0d444368b69adbc4d847cbaf8cf081cea54c319e4ab1da08b82f3f4ef09937ec7588804a008af19693bff5139164514fb3ea6dd4b18d5cfa0e9a216d9f31150c5503fbfac73821dd01ef9580ed37e1844f9d3916bb7f733e3a069bb48e9322cd87baf22e5a2c90bf60f024a300fc3ddd1fc4ec35e5337050304a0e27e8aeca2faa2e2ed8fab1f6f4e0cd9d438b80d697a12170c3255af81b0523aa037fb18250d5c9a74940976aa224e08cccd1b5a283b4b2b8f1d599a14dd06395580","0xf90211a0eeca7c52bfdec01ef1a1c948406d1cd95c628a48bea99cca08570e4c48c280a0a0f1a510919c07d8539a9e7611453ac3f4b64e575355b8f0a1c58f3c54dc1531a8a05058a380b065612ea7cb9a7b45174068b6f71665fc21ebb73dafbd4570b6fa14a0684ceb97baeac2a9c3b5a14118d4f578c980acfc7189ae17541ae56e5407c2daa0dccf7318665d89412fdffaa5a6741d11b9cb529afe504f770eb6c0c748a608d3a08b71dd67c9ff6ea323b5ec1302bd2d6437816d0a68bf4b29a48e162c8c61f7efa054ee7698a2ebb6c3aee700b66eabb34e688efcc8001be7d84a75d5963acf4590a03683d52c2d25978986f9323766a8774f2513568fada5cbaf5a549e1772186709a03412ecb9bc8acdb503195da735e1ab9918d67638ce321eed7568a33f934d3677a062c5adc422d6393b0e5d69b4c313ee3cc342173e89ee610f8341aaef66b226a7a02d25b88a1116baea226ff7b3fc1cc88c2082a14b8eee6d8509dc0e24b727400ea0f2cabb17d69bfb117c719ac9c0d0d83015bb8e7ae30a468097ebf31cd09b6b43a0e6c0bdc36fe19040267d532d6dd7819b0e62ccd920550dcac631a58547e6d6b4a0399cd0904ea2242055795b194f1bff9450adc03241c9d55d8b15c322b047efd0a024b441e9cf163baf28b3771ec177c5be78292b0fef3978b9be425042b2b017aaa044d4fc328e00beaec2a5fb43b643716f646c34fe76a1eaea963eb6b4087137c480","0xf8d18080a01a27c49a5a77e292b591767f76ddf2bfbdf1752a5b53c7f07c519d0868760d2ea0ad6cb523f73649d74c1213abb948c10037a7a342ede5cd373b6060061d79faf7808080808080a0d8825f40f808fd1d368ffd5381e2926d2263bbbcee3fee5a1aa7401328da3402a02dca1cd7f04d0fd9625b649903883a2faa52ea6cfcbda738e61f6ea6322328cd80a099fec790aed90a5f7cba13d2cb2d22c79c6e737b5673133796cb831629ac3cbba0d327ffd4270f97c978c638645dc59c0a8ed42fc09bc538c9ad91eea990f543fd8080","0xf8669d3ad8a871b31cb3552080711d61fda45242133e0695c60218a95533aa2cb846f8440180a08af15fe9c3fb8fbeb9952e1f0a3ca415821af2225ba7ce0a31c2d2f85cf53a28a029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0x8af15fe9c3fb8fbeb9952e1f0a3ca415821af2225ba7ce0a31c2d2f85cf53a28","storageProof":[{"key":"0x0","value":"0x18","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf851a07857fa9fae1428bc873b55cd9278c7389972f3a3e4be1b7ec97126ded1666be9808080a0a02d6b52757f7816acf5f459d06658b3af5d944bcadceaf803769ed1ab55fe63808080808080808080808080","0xe19f3decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56318"]},{"key":"0x1","value":"0x23d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a023d5345c5c13180a8080bd5ddbe7cde64683755dcce6e734d95b7b573845facb"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","value":"0x2d52cf40e376d0c501b301647a7b79778e66b32a34ba27355053c342bf0ff225","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a09fe5155fcf03f486c25368e95c45d5cba7db086506a6b4f9a6bca797ebddfdd680a0c361b0facf1b56062bfe642eed1e8bd00b3e55df0f31e506b8ffbdacef26338780a09544d59ce1ced6a78e8c313ffa8a8d541462fb6d1a8b22d112a0bd39e1d20c05a0d00397e2834494f1a87bf191a87949460420888522835d3d435e06568b920e8880a0046fbc3d47f51140d92c099b92c5e03645a1740c42fc1da6458341d67fa61de68080a0adda1176b24bf54a2c0158e595ec0544e277c7673613e472c8ce783b4fadf833a0537202350296d8af166dc6d39dad42dba0bd9e4e9023cb0617de351a29a74678a0d8b3cbdfea9f1c9c18695c20ec0fcc61d720e048764997683dd061cec09b5e8f80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a02d52cf40e376d0c501b301647a7b79778e66b32a34ba27355053c342bf0ff225"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","value":"0x95254d30ee04eebe7dec826096d5ce0b635474714dcb610d3f23111f71b8a981","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a06103cd09f1acc2345cd3661cf80773fa786a58aa1000d776ba6a8d7d1fa95bfea004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a0f9c0b2156072e728e82a583460ac26e9b75f687388d79049d13a7ab29327771d80a07e91bb60abdca65a3ef360fe9bbd2fe17716bed7fa67bcd7607ca555cac1b501a0bbf80a673c67484bc593ead364b21f4789bb90e9c9d08114dfea08cb95ebd2f6a06633cf42917c5b16425df44ba19ca9ae58c1df7cd3038246724a4852e2b65996a01036b6f56d3bac8fe7ad637687eeb7ca20184b898f24678b4fa1d7745dd9660aa0558b02055c29f0b66ff195b9b9fd6234d5c97fc40584701697ac12e5e84b9452a0a2aab2c8c547a76c552e0cecbe7edb5cfee7a83866967305e1b464c8263c01cba08c1679d8cdc9ce14b68eeecf0172bed65e59f98f8bcf93021b0977f2cbb6894180a023fc3db22338cc8d6b06836e10589aff7e7f73fd8a2e17b7c8e02bca86ab075780","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a095254d30ee04eebe7dec826096d5ce0b635474714dcb610d3f23111f71b8a981"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","value":"0x39b1cdf063f1c717d4a5450f1dbbc5683dc242cc8600ad7ec5ba0f7ddff664bd","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a007c522ccc7cec8771c7e60104825e57a88fca9ef833a368cdfa592ddd17db1978080a0a3431507a80e92ed617c99a803bb36ab27f6d1085ad26fa4672ce91b5c81947ba00bb934ce449a830b198be4cc1fbb3efb43aaa12dfd15df18581e07a33fd2592da0dfec69d15bd73b0b06344b84e6e9cba847c7e2b1c2f19ea42f96563668661ca98080a0c046a31a3a76fb07795fec6bce8ee2d58d6da9e053eb196e6d99f0871dbb32c180a0d64c5137b3bf612119e481de1f286855ab03b5a89205e847295cbf7ece0943bfa0880ad135a503864e143431baf513e4da174b3827a1eea4ace002be0d4c15715aa01064dbbc60b97bb3006c07aa9e92982aac85f33b477863f2bffe3ec701fb981ea0e5e159a9aaa234f1b61d05b54844f17d3f28de3e8cbbf4f78bbe80ee5828c9e3a08ed0b40704167fb82194ea0cf45739a72b0f84f0f3e6c7be89ed220eafffd6ac8080","0xf851808080808080a04dd88bb04fac169bbf3c4a222c80b687a630117edaf83e52e13ca6cbbcefe1b980808080a0433788bc4a7a09b0d2faeb9c2d44f28b8124825722a7f23444f114f30ee369938080808080","0xf8429f3695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a039b1cdf063f1c717d4a5450f1dbbc5683dc242cc8600ad7ec5ba0f7ddff664bd"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","value":"0xfb788431a92e686f4d81f0767215180c693f398d464eb15bbbeacba887ff5db8","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf8518080a09dc15af3498df1c32e3d7bf390b3ca1fe13468962f67892a7346bf05e69c259c80808080a085fb7cc7bd0c5453a3fd70edcd8bf776001862e836f68f5711ed83016563a933808080808080808080","0xf8429f357165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a0fb788431a92e686f4d81f0767215180c693f398d464eb15bbbeacba887ff5db8"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","value":"0x5c257dc4db482d47e778a821c16a0e40b2db88ad472d1bae1730e1906ea912a8","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a09fe5155fcf03f486c25368e95c45d5cba7db086506a6b4f9a6bca797ebddfdd680a0c361b0facf1b56062bfe642eed1e8bd00b3e55df0f31e506b8ffbdacef26338780a09544d59ce1ced6a78e8c313ffa8a8d541462fb6d1a8b22d112a0bd39e1d20c05a0d00397e2834494f1a87bf191a87949460420888522835d3d435e06568b920e8880a0046fbc3d47f51140d92c099b92c5e03645a1740c42fc1da6458341d67fa61de68080a0adda1176b24bf54a2c0158e595ec0544e277c7673613e472c8ce783b4fadf833a0537202350296d8af166dc6d39dad42dba0bd9e4e9023cb0617de351a29a74678a0d8b3cbdfea9f1c9c18695c20ec0fcc61d720e048764997683dd061cec09b5e8f80a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf87180808080a0cd681671de7469b3b477af0cf6d21ac8ac1ffdb00023d61b2a0d32bd577e4afd8080808080808080a0c64042becd2253a1dda3bcce4a06612ec632aeb61e84bef3170dee942811ee62a06553bc31e3c595f52fdba16b48dd7cac5c3046823357c3140edd803a7090c03b8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a05c257dc4db482d47e778a821c16a0e40b2db88ad472d1bae1730e1906ea912a8"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580","value":"0xa78b8e772e2235c3777d75526957ecb08bb0681b47f5ac2582bf0add4c004185","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf8518080a0cddb6195608409ce1e3af7bcafb1438332c340b7ca526661a0cff52f7acab826808080808080a09a1a77e2ad05e8178da178bf660822cefdb0572bf5dd9dfda7caa1266003d84a80808080808080","0xf8429f3f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cea1a0a78b8e772e2235c3777d75526957ecb08bb0681b47f5ac2582bf0add4c004185"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585","value":"0xdc923d47f18818a25c44302ef12ab6cbf51354749df66dbf1676622737c3d6dd","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a06103cd09f1acc2345cd3661cf80773fa786a58aa1000d776ba6a8d7d1fa95bfea004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a0f9c0b2156072e728e82a583460ac26e9b75f687388d79049d13a7ab29327771d80a07e91bb60abdca65a3ef360fe9bbd2fe17716bed7fa67bcd7607ca555cac1b501a0bbf80a673c67484bc593ead364b21f4789bb90e9c9d08114dfea08cb95ebd2f6a06633cf42917c5b16425df44ba19ca9ae58c1df7cd3038246724a4852e2b65996a01036b6f56d3bac8fe7ad637687eeb7ca20184b898f24678b4fa1d7745dd9660aa0558b02055c29f0b66ff195b9b9fd6234d5c97fc40584701697ac12e5e84b9452a0a2aab2c8c547a76c552e0cecbe7edb5cfee7a83866967305e1b464c8263c01cba08c1679d8cdc9ce14b68eeecf0172bed65e59f98f8bcf93021b0977f2cbb6894180a023fc3db22338cc8d6b06836e10589aff7e7f73fd8a2e17b7c8e02bca86ab075780","0xf843a0207c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422ca1a0dc923d47f18818a25c44302ef12ab6cbf51354749df66dbf1676622737c3d6dd"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58a","value":"0x28240fd8b95647d56a04b62c86bc4e5a78203ff5c3393fe86482de080d0e90a6","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a0c10be40210eaeafb7affb37be1cf73a8d79ab6fa11811f92ef9b383b5c28ec3c80a0268940e99b915692f0d70fc16d7913eb67200da8170a5246eccc8e99413e35f080a0dc430d4af5cd2ee1b45c3ccbd3dd056d439593455787b501d60329693c1960e2a017e5b7ec0b1e27255728acb3ba13a3a7d97db3543a86e26f020e7314fce5af3e80808080a0ce1e04072f90d7a1e3da7fa8f38a01770f4f3f42283c600ae9b823b8e5353a31a00d53f5d0ae5101da621781caa1e7ea976fc73e36bc4c0024aea79f92384904d5a0424a41de56b820d7c5bd231be063b86a6f94a67a7aec4b592b37abe768886ca280a0d370dc8aa939bf4b8b29d1cee7ba493bc77f9b1e876133880c080bb0c8353aa08080","0xf8b180a018235be78684e641db774248330c6d069c014248394e2e05d8ef170a3430bf9aa0d015c8e57b24dbee103560df45cfd8362e487b63c8dd8bb0d9067b17b2a322a7a0f0cbfe7fa273cfbbcfa9c3439d44db08d99b6f8c511c84a9e0bde7a10c2f34248080a008a98a5e6c395d0392a114ce84d56d94fa31649c4b81ae9d544db634674fbfd980808080a099b1d48d6d8d9ccb1a75e184ea5e013e7cf5c7c5ff1edd72a0a343bb44c231db8080808080","0xe216a0047ac7de0d120fd6480927bfd9740c37ed9e6b562a9190b9e6f6f3a6dd120c34","0xf851808080808080808080a0fe9a758713c23aa4184f64c749e72340046c9bbeda80b5232df250e76f1d35c68080808080a0d1d8219af8b8ac923c57c310ff1d1c21b53e47b06592d6d529261f0abe70819a80","0xf8419e3ad336e69b72e50a4cec1eff1aac27f3fe4a9e50ec468c2897f8dff1de35a1a028240fd8b95647d56a04b62c86bc4e5a78203ff5c3393fe86482de080d0e90a6"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e58f","value":"0xcd9a4109290d0a69d874b9df41f1119ea0a89a074ed4facdef23938856ad21","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a073311ca6ca74da12c2929d6b0147d44648daf9ad644a5a8a44d105596d0b7ee1a0e7118dcc330222388627232176de8a6aeac25659a21c504c32ba0b54c545ef6780808080a0f1e1e6a1963da281b65e26a5237bce3fd09b9c9a1f0e7ddff218b7e53161b360a0c96daf77227406fb0998d1457ac161698cc241a109052a82a74db1315d936c2b80a083c7d6321385cf0b373c8867bfaf9ef73a28c19f5a5c285df71f5aacdbde76a3a0f6b561dc7ab1c1be3744ff2503d569d967e4f0db47300ecb9515cfffcdd39481a09f5cede4690b5ffc688db0d5bb176bd7b95b0e8247bc23248485c649f581e47da01ca0374b90719499783a9848bd1f9a903144d40c02c73612041ee835940b421ba0dac9b3d0a1b0305873a97e2fb7542240bbac4aaec608f612022c8cb3fde00c2680a0dfa0d96c7762498735ac486aabe3df2b014a150161dbe5e6356dc548500deb2a80","0xf842a0205143fe78dd07f761078fae2a49104391f8c5ecb644c7485fe3e51c004c1ca5a09fcd9a4109290d0a69d874b9df41f1119ea0a89a074ed4facdef23938856ad21"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e594","value":"0x32800a926a5b9a99a6d483c673abde97967bc214e83b82f1fb9cb4068c72474f","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0c5c4d600e8237c5f052e7a4fc9aec09c22884401dec59443694deb4b9418324780a02a6f27850ba820ca67089d13837414acd6bbc1acc82e094f45fa1c2c00406eed8080a0e2a57e168b71096b928357bb9350ebc53dc31ecea2cbe5f6eeda70ee63e7feeea0bb0c8623a00fbe57b61cbf26a353088a0d5c78bca40e81697579b59416e5cac1a023cf38f358412e2975c90da2a25647a4739ea853ce1c178e05b9e8d5bc07d51ea05100b51ce8cf50451300450adcdbb8eebe935afa2b283e69a4a48ac80ef45c7ba0e3b3cd35c91710546ba23f317d666e416ce399489c752a0e59f58b7a9d23a41180a0a7df0f5c2008e7b9cd9daac967ee2823014f018659a4e0162e2a6616752fd4eca02198ceee682380630891777c2babb47f07b64905de79a141bf2d5fd66f9dec4b80a01b504d2406463a849075d4593790e6700b882f94adfe6cf23bc7f5b7345ef30180","0xf85180808080808080a004420e11ae357a6902c99daad0cb70dde57bd374f6d2d4804d3e2dd70180a63b80808080808080a0b2b3100e55edcdd3c5a8998b2a73751b4353fb1ab58bd79d8e96550aaa8f552980","0xf8429f396013ec5db4774639d8122f0250855863bdf6ebef9b8684e35a974ac0d691a1a032800a926a5b9a99a6d483c673abde97967bc214e83b82f1fb9cb4068c72474f"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e599","value":"0x42090ce68c0a1f87e43c254619b2818034ab8e4cf395eeaea5894d969b4f852e","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf851808080a0899e4eb360e9d5d048b1c081bbea9035ae1bf6a1bd79797cfd951424825a79a38080808080808080808080a08987b897c62c87bf86cd5e9f7f64cc1844242afb9a52032b327ac1df191eec0380","0xf8429f333a0afd8ad503a4deca64018725e39899b67d809ff73257df83403094acf9a1a042090ce68c0a1f87e43c254619b2818034ab8e4cf395eeaea5894d969b4f852e"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e59e","value":"0x5966504cbcd3907f9c58424ea70d925a5734fb7dc0204888795ba5a81f363c45","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a0c10be40210eaeafb7affb37be1cf73a8d79ab6fa11811f92ef9b383b5c28ec3c80a0268940e99b915692f0d70fc16d7913eb67200da8170a5246eccc8e99413e35f080a0dc430d4af5cd2ee1b45c3ccbd3dd056d439593455787b501d60329693c1960e2a017e5b7ec0b1e27255728acb3ba13a3a7d97db3543a86e26f020e7314fce5af3e80808080a0ce1e04072f90d7a1e3da7fa8f38a01770f4f3f42283c600ae9b823b8e5353a31a00d53f5d0ae5101da621781caa1e7ea976fc73e36bc4c0024aea79f92384904d5a0424a41de56b820d7c5bd231be063b86a6f94a67a7aec4b592b37abe768886ca280a0d370dc8aa939bf4b8b29d1cee7ba493bc77f9b1e876133880c080bb0c8353aa08080","0xf8b180a018235be78684e641db774248330c6d069c014248394e2e05d8ef170a3430bf9aa0d015c8e57b24dbee103560df45cfd8362e487b63c8dd8bb0d9067b17b2a322a7a0f0cbfe7fa273cfbbcfa9c3439d44db08d99b6f8c511c84a9e0bde7a10c2f34248080a008a98a5e6c395d0392a114ce84d56d94fa31649c4b81ae9d544db634674fbfd980808080a099b1d48d6d8d9ccb1a75e184ea5e013e7cf5c7c5ff1edd72a0a343bb44c231db8080808080","0xf8429f33044b54848e2f9d80d11326f7863e89e0aa334f0710afbc6568e6663d3b56a1a05966504cbcd3907f9c58424ea70d925a5734fb7dc0204888795ba5a81f363c45"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a3","value":"0x173381a2ce0b5e7ae9b08055980d8cd5caf104a702cc63d297c2077504df2e82","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a08a370475f78ee1bc03580b2b2e9b16b1eb452f81212a9d8127d954e92fcc8fb1a0c1bb8ecd59b80bbed441ee18ebdf94811827f628bdb0bedb6ead37e24c92a95c80a04c7fc64651499fafd4cfc77092da4144ae626a73550cfdec5930df2634af02c280a0e0a013bcad6a578658f28a4049f44e162dfe682797a6c9a5244345a02ae649178080a07ce04089b42c54d91d5b5f41b630a99a7661d48d1bc0c39a4857180f7a418fd7a0729f553b90c8aa218b3b985df9d1ff27e0a6711f1468b0c6999f1a92bd2ac070a096be06c6c4b4ef62086038abdf758a47ab47d0f88f1c8d45ffa06ba2d1fecea88080a066869a20a67748f29010705a43fb0cd62813f7b0090eb66250ae7c8666fb4c26a024c22df91486e78fda115ca5ca3607933ff5b04d7c2977621c24f05f7d3ec44ba010a870fe4501d8e2f800e4d73623d069988e94ee790123f209e3d7f425534eab80","0xf843a0205b1bcd89d0167783ef3c9078f5aba26b1dca729632fdede82297d26b9ef672a1a0173381a2ce0b5e7ae9b08055980d8cd5caf104a702cc63d297c2077504df2e82"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5a8","value":"0xcd89dedb22833e4a192180bbdd2d0886030c067c6e22921bb39104cf62831f03","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf843a020c483131d4db389081b171cc303f3a6b15777cc81e0f66f0a8c82d85c6afc49a1a0cd89dedb22833e4a192180bbdd2d0886030c067c6e22921bb39104cf62831f03"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5ad","value":"0xff04decb90109c6941ab76457d0449c666f996c430e546e6c0655aa986d621e7","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90151a0e96607228720bed234b27bb0c37e50e491a8938bb805526555881c355488fff8a0cf1bb0975c1421732acd6e4355d4be5a5cabef4b1abd7ad1567c30acd41ab25ba0c8ddf6cc85a6db42ef4c698c4fafeba56c74bc420e7faebffc427f8629af5bbe80a0e48ac1fb66db5420c7589d28982875f6b00a01bf2550410419f57b1d5b2b8f5a80a093cfad45cd604cf4106e82ba40a6b52b55d97e5adcd18cce5cb2b2ce0e96edc8a00b70e702a028a1c36668a44a5737e4233057f7ad89cf96b20aad4dfb02c47db280a0be908080ee7e1bf33568ad4544dbacb39ca16330d86404c93ff9a2325842b633a0ba4f73ad2d3895debec7bffa1d095b66b3f86037d903e77fd3d6d09c601a73ffa0bd4e347cf4e458ce6fcfda1400aad6be52bf24776122cec6b81565875f7efa318080a089e93950ee646c6303858c03da4f679895f38946ddfecd12750b072b785d5b6c8080","0xf8718080a0c3e6f2dca6ca60e59ec4f46d3d3d49f73831e6b2d122d6748f39b52db95a51ed80808080808080a0a32a488bdfb8c49ebb54e1e35b317b2e2abf2b0dc9f787d1b43004c8593d691180808080a074957c7f195e2392b3a02f0652ad9c11ff09bda6aea34ffa6d9d0eb44605b54c80","0xf8429f3c2fb1c8a64dd0ef4342f68885ab9cf9863beb0f01cdd1a8b305cf747368dea1a0ff04decb90109c6941ab76457d0449c666f996c430e546e6c0655aa986d621e7"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b2","value":"0xfd2c0697de5cd00ef86910c06ae2bf47697564816ece583c6c3d70bed9c17ffc","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0bdffcee71e093972beed24f272c1c141161690138d7e3b6aaaf19489355d6e548080a0554c5f473bb32eea8645636e6b9ada3625008e956f75891c946eed555f608a1ba011585654818deb63d9a08c124a0245dc2a9b457323a521420cf9dfecd1222cd58080a02c4cb2a2fefc5b225a10bd717ff7fd225ea362dc5eaa71091b6fca5f3ee9d19b80a03e4c86cc1f186bfcc333af8847ecb8e8e0607172537fab56ec62e17495a7748fa005de0aa6773a0b4d51716a986ed7631a65f256a02f3f6b529d9ab0f713138890a0972bd683b0bdf4d1383e11b0bea7b23c0d92409b48c540367335c6f371033908a063f6fc4a406b7bb140217ed6520b603ba669f17cffbb76886e88e22b241a51dda0587d72713f85edbd55ff0def84b82bab4531368cd2050deff0e360c22a3ef9c3a0234ce860f0df77a2a1cbda27ef75fdd13977debe9955742cd50a1e426ec5473180","0xf843a0207c993cb9ca55cb4f25d3214b28e970d532ed00e7124447c6da58966abf59e5a1a0fd2c0697de5cd00ef86910c06ae2bf47697564816ece583c6c3d70bed9c17ffc"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5b7","value":"0x3038277c5c0507dda59579d580e57e020f580002b2a22b7b91ca65d1c7aa979d","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90111a057f54bb76bf601b1a8d3be95c811096f5cc05787b74e9b398915b646d6cc93cba083a1650ede482514d207120e4f12614dd60ddd2c078dd92bafe58b412c08200880a0653b618d408054a81ab50663eb4010377d1d5fad5aa003c3c7edada1280ff19b80a0b7490a2e96e69005de53df486532f9752e56ae7ac3139ff149a5c0dbe83571728080a02c4c3e10fe960e892a34daa718b69dcfe4aeffa65dd3cd930a0b762f7b9a81248080a0bed38aa7ff016abfc4b28a740eca1f26d4cd53e43f80ffb14fd38983ad41f37ba06d39d773924b6912477395d27b3484e97e4deb16e78e3bac59c94cb6ca8a10c88080a0674867e8bede0a3f6391aa87fbb2c06fcbb80a9c212ee57c34e455064ee3b38780","0xf843a02037c1cdf00f527d465e035eb85038ec025421aafa09c17728cdef4c0319f3a6a1a03038277c5c0507dda59579d580e57e020f580002b2a22b7b91ca65d1c7aa979d"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5bc","value":"0x4ecd9372b3d3b7db017cc21d0e754aa938b0503b3ec62c3b185f28e642ff8efe","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf85180a033e335fdda5867c48e7176f889fd7e279ea732ec1d76ca319bc12bb3ac87dbc8808080808080808080808080a07c1f795f905ad3d54ffec5c4d1e5ad7023b74ebc39a3770e196bb286be7f74388080","0xf8429f3414becb71a9e265bbf779d5dab884471ab07491acc55da004865722dd9555a1a04ecd9372b3d3b7db017cc21d0e754aa938b0503b3ec62c3b185f28e642ff8efe"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c1","value":"0x56a1a001b6ac8efe113db6f9997650234e253012fc29ac138ea88c7bbc49ab7f","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90131a0e6ea1e436f05d24ac984b6d75fe4246a9abe453816406276c3dcbdf80aad793780a03fd646fdd60bafca2096ccbcdda65a7e483305274e3acef764f2643ac0f7cf4580a016d82c45afb190bbe73c553fa3e9821e6faf80178822629e44966602d77405d6a0e616d9d455b9c021ef5f994756cf8ddaaa914f4a01e67a6f709f6cbe40e2d1b5a0ac90db5c3bf7cebb036347ff37ee28ef741711f3deabc288b32be6774fd7846e808080a0f151043c33fd525061b5093bfa289c69b2e3e6d307346e9d1f8b27daf02e4639a03a517a79284f29916504e8c87b0d255594e9555472c3c5506b57c52a5ceac94fa05ae394240a0179fd6098f01bbb050ff08fb0434f03d322063f0f7675b020664680a0468171e6f3b407f9a89fb7a40fd580f7c4f6a7183fcfe57d4a0737c9e287c5e78080","0xf851a03a237803b2f954e84d1672d67c63fc386beab8ad6a39c969992dfdbaa7db20b4a06dfc98e7ea0bae439ec4a91accf600766abceac32c27e75b9bc0299142a9a952808080808080808080808080808080","0xf851a0c347cda866a395df2f0008995d90a0944f9b00181ec017bae9946945f83e0ca28080808080a0b25c8fe5663d6223e681dd230052cff9714aba76bb351cefd62716916670254280808080808080808080","0xf8429f2049a1b7f41c7253d14878e9f3078f7c30bdaf197b7843b5e995f3205b52eaa1a056a1a001b6ac8efe113db6f9997650234e253012fc29ac138ea88c7bbc49ab7f"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5c6","value":"0x805e8f379e8c46ff832bc1de4c18dbdd4298af7980a2baa510f08bf6b535102","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90191a0625f8d33fc0be884a044b72b5d1e5540c8438ba229cfd1b3cb580012dcbfbf96a04cc155a7733da13a4178ac150af3aae5a546d5e852b88c7b2348995d26614cfd80a05873c62aaf91429469acbd060af360a0f8858aede4e7554e3289f171f2a79e158080a0905337c7334612fdb0e2bd6f5bbbe7844a5b2e68121bad742e449cc0b26c8bd2a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fda06ce2fb704d930c53524fbf883e483d598b6869cd479598391d8d9974b5bcdf97a0dfa06820b792d37d80969f0f46bf43fb698d499a92c3bb90f7df86da00456ab2a026056fdebd58e774617d2b76dfb0bd14f7863bf6abcf25ba1c76e8527d4d79c3a088606f96a26074bc1ddd07d867f6611662a0a90809339d57d25635382ac9dfeda01a803446fd04d71dca9cccbce730f278d71629c08a92b173b3f67806eed94121a0bed418af7fb2c79b05d23d46e280a7e6da507bc02babb0437bc8a8bedd76d32580a02ed77de2ba88f0af119aac155e22c23dd35fd1e6d35afb3a90ff6e0788855d2780","0xf85180a033e335fdda5867c48e7176f889fd7e279ea732ec1d76ca319bc12bb3ac87dbc8808080808080808080808080a07c1f795f905ad3d54ffec5c4d1e5ad7023b74ebc39a3770e196bb286be7f74388080","0xf8429f3ebecf4879f2388cfb4eef3fa5b2610d4742229a536a7abf3fd78b590e515ca1a00805e8f379e8c46ff832bc1de4c18dbdd4298af7980a2baa510f08bf6b535102"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5cb","value":"0xff217f671595e9442df0d21b483dbde49c2c6eb26a7552e0895093f6785299d0","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf8518080a0e140d1028a275a6d0769bc27299ebbe580d038a5d9ce720c31089a322da4965480808080a0e4373dc598c156d176309d2a09ebada130fda4c55acb3cde0edb631a5ea73ff7808080808080808080","0xf8518080808080a017be900871218000002e77f12142845ac02e201f0ca9b9de5d887d90d44c6def808080808080808080a0d959ac4a10a578c1773a4356347b2703bcd03bf7cfdb3b7a0fcc7ad0768b8b0080","0xf8429f20c650d451c01266e75135d143f261a021319a4860f12f807e625d9a446910a1a0ff217f671595e9442df0d21b483dbde49c2c6eb26a7552e0895093f6785299d0"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d0","value":"0xa14093e2f3dd910e6264c01acb8fb0c13b120a7fb5ffd97781ba06b6679d2bf6","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9017180a05db83fdd81f6090f694fe376efd65a0cd12b8b860c73c61b62b309c9117ad8e4a05f488251881619100ce873df1b38463a17d107cb0599e2307806e3024ff2de7ea005e52ae30aa266f969b979acc16fd19e9d95385ded961073736d07301a207a9880a03e33b2fc18f6c4f004ab8045d8208fbcabf814590732f72fdd512539c4a39723a02a12b79deae8f4815b15d19f3fe7209b828739dfecaebd686929a5a3e546c30d80a003301dd18ff8a58b9744d88c0efe2dd68294b19387243bccf37e07b7e82600f5a00bc21c893de4da817fb01762e853c315804f8b9c6be34e513110d10aecdae65aa083a890a2b7928642bc990d01100602473dbc6c93bb220a60dc063bf6590473a18080a0f302ac97324252fe1d0ce29e5ffdf3c20e1ba5b58706c922e39b381560912010a0c268b1f0ba065e0715e965a2a88d47b4e5613bb8811b13d87793fb5d0f833422a09506a8434b8d54272c88db5524fffe98ea3a3319d79daa813ae766bb20e9436980","0xf843a02055fb40d3c79c636ae8a87d67d6156ebb0093442a7ba8c3574a9ff1683c5901a1a0a14093e2f3dd910e6264c01acb8fb0c13b120a7fb5ffd97781ba06b6679d2bf6"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5d5","value":"0x96c7f94de6cbdcfc22707452e5d1db3d931d9dd5e9606d76001ee471f2749911","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf90171a003e7005da988fb98bab0976ce7b30b8bc549430e6fa0954b526cb81652906fa48080a04ef8afada5cbe91329383947730a2f79f908d6cd95efc110936b432c6dd58ae9a05b3bed46989e3eb26afbff75332bf5c6a7d2b0a44c131c75c47e6cedf4a5322fa0db067b990c6ec29ec6bceb1b8744e8a0947e4b76a3ff75a52282cdaa0fe3760c8080a09aaea44cc476f3b93ba2b74c3550762e10c1ccff5cd835b8a3098b2a89cb845e80a027d38b7d350dfcca44267ff43a85dc0d306b4f10ffadb1851b37a8282fe44aa7a086b2ce2cb9ac64d3c8c8426c61e07d433bd80f15722dbe5c47a5208fa9d984daa06d8f7a0491aebd58c70a001f023129edb3d26d0ba6598d4ee480295ff17fdf4fa03ef00b563fb55c78da22bd857a0e93223a11e1cbe36df4405dce586f65e0c356a0140b94c3d0456269d059a4c4125cbae9911fa10f1344e55c96e2124140f0dfe7a0890bdc2e6ef9310f0a4affd4de97feb8eeea093858d74f0b0a3b0ed557c9482780","0xf851808080a0899e4eb360e9d5d048b1c081bbea9035ae1bf6a1bd79797cfd951424825a79a38080808080808080808080a08987b897c62c87bf86cd5e9f7f64cc1844242afb9a52032b327ac1df191eec0380","0xf8429f3d6e65807074f2c436e5186a2d89868587438e310ebcb745d33740f512e150a1a096c7f94de6cbdcfc22707452e5d1db3d931d9dd5e9606d76001ee471f2749911"]},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5da","value":"0xc371c32a765085f87dcc307150f0fd146419ce9afddd9bf940a035223c280e23","proof":["0xf90211a0385ced5243cdf2896972bb9308e46e495cb2c03722aa10ab9391a01982a68969a061a54bf87d397f38ac356fd3cb5f95e043726e6b899da8d4cf82051fac6d5bb5a060009bef28f7e27a059c616ffb65b40952d1ef3da33a703b881408165b0d9d6ea06f38996fb3c789470e6ff6b4ba6a575d20e2fb7f604de607a4d5f9e416e95958a0884356315041d41798f53558a3d2b292b05e2a477632a1488337ab9f85a9781fa092cc1cc9804c55a1c254de5e327ecf3443db9ded678fab119e879748913c6ccda01cb4108edb3b23a09b5d9c61cd7740a915429b38ec76f398f562396625d4b045a088b23a9a79e1d944430302fb910575a76309d52e99eb5f78716e4d9cc91c4b98a0292456129fb7878da212fb91cee5248fdd8d54a747f3e7dba644351d5a541650a09a5bc559d679edda76ee1041a535354b507cdc763bb9c3f0d4ee2faf379790bfa0b03a80929005d5d7f1e5f93cb15e853d35582a6d0eb0c35030f7eb95000c4e1fa0580bcab639a165c7d8e463fe59d001e1595de288b18f822f8079635f39bae05aa007bd7fb0f32e306bfe70b62b27820d7e8c41836b689776d9fa958fec3c0b3b2fa06ff4ed4fb54b258464e426a03131f8f65c2a5d2368c61317ba9ca2ff2b35ea89a0aec7de8f376d67aca9c7a478b6f19eefaeea4075c5ebd6859b53cccb98c7ac08a063054e722a9091aa337f7ff8d717a60af0198e5a2103b31488fb498c83eab22a80","0xf9015180a0bdffcee71e093972beed24f272c1c141161690138d7e3b6aaaf19489355d6e548080a0554c5f473bb32eea8645636e6b9ada3625008e956f75891c946eed555f608a1ba011585654818deb63d9a08c124a0245dc2a9b457323a521420cf9dfecd1222cd58080a02c4cb2a2fefc5b225a10bd717ff7fd225ea362dc5eaa71091b6fca5f3ee9d19b80a03e4c86cc1f186bfcc333af8847ecb8e8e0607172537fab56ec62e17495a7748fa005de0aa6773a0b4d51716a986ed7631a65f256a02f3f6b529d9ab0f713138890a0972bd683b0bdf4d1383e11b0bea7b23c0d92409b48c540367335c6f371033908a063f6fc4a406b7bb140217ed6520b603ba669f17cffbb76886e88e22b241a51dda0587d72713f85edbd55ff0def84b82bab4531368cd2050deff0e360c22a3ef9c3a0234ce860f0df77a2a1cbda27ef75fdd13977debe9955742cd50a1e426ec5473180","0xf843a0206694f21c46735727f9aedd8541e81c27d760e39807330e4846d12048d0ca7aa1a0c371c32a765085f87dcc307150f0fd146419ce9afddd9bf940a035223c280e23"]}]}},"signatures":[{"blockHash":"0xb3740c92a5a34d5bc8e70844dac38875874ca844c9796c06687e31c7f02dab81","block":9935255,"r":"0x9dad25619e497de4f6e0729a30e3aaf05f12eabb32453b49212b4c3fd3ea3c4e","s":"0x4a462f8192eee20ce62a0acbc3346a0643007ee26c5a21784a6a1b761c983be9","v":28,"msgHash":"0xf72a9cbc9e38e6f8834ab4837edbd4748209c56b4c61742668f1c3b1038177d4"},{"blockHash":"0xb3740c92a5a34d5bc8e70844dac38875874ca844c9796c06687e31c7f02dab81","block":9935255,"r":"0xff5b7e2297868b5634b343e961578e2f7fd5cf1f73ac9e1074c5a57e98111102","s":"0x25014eed7719c2d564b481a15279dec5fdd51b661a58f911df42f8cc84a1cdf2","v":27,"msgHash":"0xf72a9cbc9e38e6f8834ab4837edbd4748209c56b4c61742668f1c3b1038177d4"}]}}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/goerli/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227711,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227741,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227801,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227831,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227876,"weight":2000},{"url":"https://tincubeth.komputing.org/","address":"0xf944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a","index":5,"deposit":"0x2386f26fc10000","props":"0x1d7e0000000a","timeout":3456000,"registerTime":1578947320,"weight":1},{"url":"https://h5l45fkzz7oc3gmb.onion/","address":"0x56d986deb3b5d14cb230d0f39247cc32416020b6","index":6,"deposit":"0x2386f26fc10000","props":"0x21660000000a","timeout":3456000,"registerTime":1578954071,"weight":1}],"contract":"0x5f51e413581dd76759e9eed51e63d14c8d1379c8","registryId":"0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea","lastBlockNumber":2561645,"totalServers":7},"jsonrpc":"2.0","in3":{"execTime":93,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90259a05c5e93b9565f27fd2323e0ff8e4223544bafae7901471add70020a096ec8dee0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ab259efcaa53f85b64d2a08e6d0add73f202bd84a3bd40bddd583e702dd96bafa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018327166d837a120080845e9eabe1b861f09f928e20407072796c616273206e6f64652d3020f09f928e000000000000004f3e9bebd06db77ddb2360dfb4296f470cb1a7f49e362f48cb7d94629d9ac52121a5f4c9602fdd793405c3cfa4a044f56f2bad06d74471f35e4600744a0a6a1a01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","accounts":{"0x5f51e413581dd76759e9eed51e63d14c8d1379c8":{"accountProof":["0xf90211a0986b44e67c78364065f5dc3c534ccd4302808c5e54046e8c80829c3f02ec5a5ea0f41c0d0a544172c8f694fdfc30ca524070ca324266250887b0b9eded5cfc2423a093cbaabf5040f8fa58e526e48980f510b9fe39498c836167adbfd10d9e26558fa0239957c929e9534d0898c3918e7dbaa39a071c80520bbc718e6255aa415a1598a0ef7b0c7dcd00b6698f2ee7563ce0e24522df2fa30284ab91ceb089135e77ba19a04f851d960beb230c751524367515f2efa1988a8d7397642f9517760605df5ea3a0885efafe537183707875c40858a29079eb19497414714e63be7769b7b748adcaa09710fb593a28ebf4c2d6fa305481d93cc8e1a73fe1a712326e7a396b8173e87fa0184410cdf04e3cc5a2b1d85413682bd45261fa77b6b8e3246bf2d3fc74421b83a0834b425059038128d790259f71cb1ba80b54c6cc31b5988eda77c5b0b0601bb1a01729490ed765805942c0473c4dd8eb1ebf48870695ed354ab413fdfc10622f47a07a06dea25967f38e0686a90be7e8bb350730354ea727b66aacb6c257ba8acd5ca02d0ec75f01087feb8a861e31e4c81edb1ceeadbe580698893ca7c620e87d5755a0888243d3b81ef932fea8d61a4071e6c96c3b976c49761b13a9bea5ee9f562f41a0460a8104f433c3550d024dcafaa00b00f12d8bbfe761526b3015cb0891eacea9a0fc3f7e541f58e8d73e0f86321b9b3c12b4a7756f29eabe682c02a099fe9bb70780","0xf90211a00fa7f8810b00c35866ce9e51cbae98f606b33846cd551831c4644288d205edafa05e83442e082f51d1a5b92355f911834947e9619dd4caf4d5580b49c5a854606aa0c84acffed121f731c9c610f36b8c84bbd28a3dc645ec7240629213bc38f64039a02c1e394b817522b0e3bfa9a3a7281f1c7364b2bce1b8f9a01fd6d3f94f8e6606a0ac40ae9ddc0d3ce574d1fe2262e54f4a783016f48a1a124678b5801436241f32a0c0d3e9bfc2ea71ce1e23669b4b88972baa9fbb022d3768cd588b8cbd2e97819ea0335400dca7d0767facca14b36f8ff2058d19e456eb3952bca5b64878b188b905a048b94a4884523518c5ed03f87407772a25cdc8af5166bc25716969baa201785aa008896064525a2ca95344d6029e739320f1a192da404e6aeddaf4b507fc376ca6a053fb7a94b2bbe151967b565157b2366bf88d1d8be7b71411f1be96f6f881e542a0aa227255ce295c2ff5b660ed3d3c1a0acd74f92a7f8bda3096edd6f13246f324a04926c06ba78c204cfb6a27cef8f7a8205c02593ee4534a22b05be0254df93187a0835ff58533225ccca499daa72852615e4ab588dba9fcdaf3ae0817da335236a4a00979c557b8ea8e63abf1986709ee520627808ff1b2e8f78aabff96ca59edc81ea048a6ff34d52373fc8f489ee4df1eb20e86e9dafaa81946726fe053429efc7679a008ab488a1b227041fdeca8df667b3eaaf7ced33ff00207dc42816a1aba7d326980","0xf90211a02da6ef307dd2df5794295ede8951fa55b03cb9fa1f93f9f2eca589aa1496e3b4a0adced8b765186984dddf8808636f5b9fbca1e95dc8d963d9d145a6f64f6d2ec7a0877b2febb7f938cb2618091ac97872b2efdb507a9f622bd549527ec85c5ae2cda07dd90d18661865ecf6a4c310ef9e31fd2d9f5a4b29d951ff7fa47b703713dfa8a0df6d25c07cdf559727e4ccbe4138ab238457859c3eda0338c761452e5dfcfc7ba0083d70c507fc9c44412651fd3ba5a163c5326d2e64a01f48c726b8e03ed56b9da034c12c74ebccabc190bf75476e5b79d804a8792eb4223a7cd50b6cad21815abba06ffb871008d6ef8aec2db58d276d108d8d321d7a7fc62b7dbe7796c71affc362a089f07662f9aa0ca8aeb5410e4b9cf66beeb29d7165edf5b5b6d645168983baa4a01461d33dbe63b8661bf74a8ca309070d4924fd1d12a653b4b1f21d288ca2aaf3a011f1767c03eb1369e076b1b3d54beb607b203ce3992ce9b15486134d40507263a0f719c50a08d073d72a923ac419020fa98bb84cb58ec399dcde7cee4d3d6d505ba0b5593c66c56c660dc7296e48f050e2f13f29a44682740368d829b8cd278cd4a5a0a24c8ea460cfe397c3473dfb6ad9df7322b57f318dcd39e0a32524312049cb6da063f4d247ce15cef7f396ebe00a089bbbb0c69e95f6827032fff92bac46358f99a076d290fee2dc3a121cd284e83035816fcb8bfab6d9eea400a34b84cffcc02f1b80","0xf901d1a0f8240485bf18da9a1e814fb6aaaaef71e6c10ebf93efc18fa3c8d3d57ee1085da08e5e2cd65a2ec84ffbc2ae1c2066139423cfe71c351a8dd42b471faeb4c05dd6a048dadf0b008e2a2dd31552cb04f8411c9b8f3e7a25e9ff5dcf3fe0e25ee585efa01f28521aec2d7a50a466f88281e6e827d5509bc5a77be74f3f704fd91079442da05ed7f0cf73f299255bfc2bdf20b31a709518fb71bdcaa9fb8fd488ad07af28ae80a07b0ee64c5fe838e8ca0c55a77fe525cc68f6390517f19fbfa51b4b8773511c1ca097a4d6d7f15b05d96ed7511e39aae51032fc3648c15eb4d789ce8916f79a78a1a0359eca8df24cd4ac526e7031b0b01f98b87f2be0fa5667e9596e96c212ed7d84a0987efc28985777345b301668a2208b099ac715f03bf56325fa874485859deed2a0278b5bef59d42d4013a3926c01c3c55bc3984951d0a51085f7db5dcc935ac7d6a04c35b4967661e70f5068aa326f3599c7393498e1b082b8b26062f98ffbb2e8f4a023d8b0cdfc5807cf338a56b1260118129ce2d1080dca624d02c1e7a44ef7255fa068665baa882f2e62da7897273881f510f3768c3d9878efdf097085ef3f0b5ac480a0d4524fcdca73a594f45be8e41613995cdd8bd38512c6932f04f6d6787ca4856380","0xf87180a05da0431ddcf9c0df5220e90991d6fafadcbb70ec9e51c042a743f4d1980df7c4a05e856a872504286cb6dbb11c85fab4ca263a72cbee0a785053fbbb4f2d6078738080808080a09922b3a2aac38c7bd2332ec05abd047f2fb7858f2d2ae4f6c49bce18b73eae948080808080808080","0xf8679e3860ace08b3156e1e8b3657a41748919bc942fd9e0f3de90d72f6e5bdfc3b846f8440180a0ee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0ba029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"address":"0x5f51e413581dd76759e9eed51e63d14c8d1379c8","balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0xee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0b","storageProof":[{"key":"0x0","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080","0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56307"],"value":"0x7"},{"key":"0x1","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a067c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"],"value":"0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a02b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"],"value":"0x2b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a00c2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"],"value":"0xc2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8b1a0f3ab6aa3f0575916e985798d7ee01e8c75436765f043cdfba2ad10f36b47f6d48080a069a129011ab4666f131c1bdac7d923dcbb6f1047057a62d6ecede5d17057658280a064bde28657cfaa21b487ad660da11e94a06a1b7f46502263094cde0407dfd24380808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd080a015cb29fd7064f1cbac8773177854799e563e10ba66e44c5adf25b31fa39a7d3980808080","0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a098d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"],"value":"0x98d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080","0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a079c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"],"value":"0x79c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf85180808080a0fe0a1c808c8e90225d5dcfad8bde23daee522b2905b605bc6eb5c39596018464808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0a7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"],"value":"0xa7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080","0xf843a0202f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cea1a0ac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"],"value":"0xac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880","0xf843a0207c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422ca1a01fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"],"value":"0x1fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"}]}},"signatures":[{"blockHash":"0x591d91aad86c59f42ac99ec76c387811508b817ce3bd490243272e85fee2e338","block":2561645,"r":"0x1edbb40dc2dd14e24a9a1f4722c58ecd55317e0c74768bd5676702e76aee206d","s":"0x76a476cfdf535a699c4df9497403421a687a9b78db250411c0ff717bc1336e2b","v":28,"msgHash":"0xa280c73dd24b40c2751b6fa6571ab5e577f6bd2f9e5c40e3811b3ea7dba7854c"},{"blockHash":"0x591d91aad86c59f42ac99ec76c387811508b817ce3bd490243272e85fee2e338","block":2561645,"r":"0x83b677e63fae9053dc2100c3eee6a54bc6d0bac0e61a95c79b236187c0ef6532","s":"0x58e78b8b3bc0c4a12c20d74f84cf64766255c1144b21196cad482400e7d5b5d7","v":27,"msgHash":"0xa280c73dd24b40c2751b6fa6571ab5e577f6bd2f9e5c40e3811b3ea7dba7854c"}]}}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/goerli/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227711,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227741,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227801,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227831,"weight":2000},{"url":"https://in3-v2.slock.it/goerli/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576227876,"weight":2000},{"url":"https://tincubeth.komputing.org/","address":"0xf944d416ebdf7f6e22eaf79a5a53ad1a487ddd9a","index":5,"deposit":"0x2386f26fc10000","props":"0x1d7e0000000a","timeout":3456000,"registerTime":1578947320,"weight":1},{"url":"https://h5l45fkzz7oc3gmb.onion/","address":"0x56d986deb3b5d14cb230d0f39247cc32416020b6","index":6,"deposit":"0x2386f26fc10000","props":"0x21660000000a","timeout":3456000,"registerTime":1578954071,"weight":1}],"contract":"0x5f51e413581dd76759e9eed51e63d14c8d1379c8","registryId":"0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea","lastBlockNumber":2561644,"totalServers":7},"jsonrpc":"2.0","in3":{"execTime":64,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90259a0bcc37678ab042332bbc273541bc6f8211556119a44a7e23b354048b6d63864dea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ab259efcaa53f85b64d2a08e6d0add73f202bd84a3bd40bddd583e702dd96bafa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018327166c837a120080845e9eabd2b861d88301090a846765746888676f312e31332e36856c696e757800000000000000fce7e174d5b4f5bedd77893c13110141522176c948489e873c7faf135bd6f7e30ad1960956047ebe2eef8cea38b07f9e320fe9909d56e337514d154e89394d4301a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","accounts":{"0x5f51e413581dd76759e9eed51e63d14c8d1379c8":{"accountProof":["0xf90211a0986b44e67c78364065f5dc3c534ccd4302808c5e54046e8c80829c3f02ec5a5ea0f41c0d0a544172c8f694fdfc30ca524070ca324266250887b0b9eded5cfc2423a093cbaabf5040f8fa58e526e48980f510b9fe39498c836167adbfd10d9e26558fa0239957c929e9534d0898c3918e7dbaa39a071c80520bbc718e6255aa415a1598a0ef7b0c7dcd00b6698f2ee7563ce0e24522df2fa30284ab91ceb089135e77ba19a04f851d960beb230c751524367515f2efa1988a8d7397642f9517760605df5ea3a0885efafe537183707875c40858a29079eb19497414714e63be7769b7b748adcaa09710fb593a28ebf4c2d6fa305481d93cc8e1a73fe1a712326e7a396b8173e87fa0184410cdf04e3cc5a2b1d85413682bd45261fa77b6b8e3246bf2d3fc74421b83a0834b425059038128d790259f71cb1ba80b54c6cc31b5988eda77c5b0b0601bb1a01729490ed765805942c0473c4dd8eb1ebf48870695ed354ab413fdfc10622f47a07a06dea25967f38e0686a90be7e8bb350730354ea727b66aacb6c257ba8acd5ca02d0ec75f01087feb8a861e31e4c81edb1ceeadbe580698893ca7c620e87d5755a0888243d3b81ef932fea8d61a4071e6c96c3b976c49761b13a9bea5ee9f562f41a0460a8104f433c3550d024dcafaa00b00f12d8bbfe761526b3015cb0891eacea9a0fc3f7e541f58e8d73e0f86321b9b3c12b4a7756f29eabe682c02a099fe9bb70780","0xf90211a00fa7f8810b00c35866ce9e51cbae98f606b33846cd551831c4644288d205edafa05e83442e082f51d1a5b92355f911834947e9619dd4caf4d5580b49c5a854606aa0c84acffed121f731c9c610f36b8c84bbd28a3dc645ec7240629213bc38f64039a02c1e394b817522b0e3bfa9a3a7281f1c7364b2bce1b8f9a01fd6d3f94f8e6606a0ac40ae9ddc0d3ce574d1fe2262e54f4a783016f48a1a124678b5801436241f32a0c0d3e9bfc2ea71ce1e23669b4b88972baa9fbb022d3768cd588b8cbd2e97819ea0335400dca7d0767facca14b36f8ff2058d19e456eb3952bca5b64878b188b905a048b94a4884523518c5ed03f87407772a25cdc8af5166bc25716969baa201785aa008896064525a2ca95344d6029e739320f1a192da404e6aeddaf4b507fc376ca6a053fb7a94b2bbe151967b565157b2366bf88d1d8be7b71411f1be96f6f881e542a0aa227255ce295c2ff5b660ed3d3c1a0acd74f92a7f8bda3096edd6f13246f324a04926c06ba78c204cfb6a27cef8f7a8205c02593ee4534a22b05be0254df93187a0835ff58533225ccca499daa72852615e4ab588dba9fcdaf3ae0817da335236a4a00979c557b8ea8e63abf1986709ee520627808ff1b2e8f78aabff96ca59edc81ea048a6ff34d52373fc8f489ee4df1eb20e86e9dafaa81946726fe053429efc7679a008ab488a1b227041fdeca8df667b3eaaf7ced33ff00207dc42816a1aba7d326980","0xf90211a02da6ef307dd2df5794295ede8951fa55b03cb9fa1f93f9f2eca589aa1496e3b4a0adced8b765186984dddf8808636f5b9fbca1e95dc8d963d9d145a6f64f6d2ec7a0877b2febb7f938cb2618091ac97872b2efdb507a9f622bd549527ec85c5ae2cda07dd90d18661865ecf6a4c310ef9e31fd2d9f5a4b29d951ff7fa47b703713dfa8a0df6d25c07cdf559727e4ccbe4138ab238457859c3eda0338c761452e5dfcfc7ba0083d70c507fc9c44412651fd3ba5a163c5326d2e64a01f48c726b8e03ed56b9da034c12c74ebccabc190bf75476e5b79d804a8792eb4223a7cd50b6cad21815abba06ffb871008d6ef8aec2db58d276d108d8d321d7a7fc62b7dbe7796c71affc362a089f07662f9aa0ca8aeb5410e4b9cf66beeb29d7165edf5b5b6d645168983baa4a01461d33dbe63b8661bf74a8ca309070d4924fd1d12a653b4b1f21d288ca2aaf3a011f1767c03eb1369e076b1b3d54beb607b203ce3992ce9b15486134d40507263a0f719c50a08d073d72a923ac419020fa98bb84cb58ec399dcde7cee4d3d6d505ba0b5593c66c56c660dc7296e48f050e2f13f29a44682740368d829b8cd278cd4a5a0a24c8ea460cfe397c3473dfb6ad9df7322b57f318dcd39e0a32524312049cb6da063f4d247ce15cef7f396ebe00a089bbbb0c69e95f6827032fff92bac46358f99a076d290fee2dc3a121cd284e83035816fcb8bfab6d9eea400a34b84cffcc02f1b80","0xf901d1a0f8240485bf18da9a1e814fb6aaaaef71e6c10ebf93efc18fa3c8d3d57ee1085da08e5e2cd65a2ec84ffbc2ae1c2066139423cfe71c351a8dd42b471faeb4c05dd6a048dadf0b008e2a2dd31552cb04f8411c9b8f3e7a25e9ff5dcf3fe0e25ee585efa01f28521aec2d7a50a466f88281e6e827d5509bc5a77be74f3f704fd91079442da05ed7f0cf73f299255bfc2bdf20b31a709518fb71bdcaa9fb8fd488ad07af28ae80a07b0ee64c5fe838e8ca0c55a77fe525cc68f6390517f19fbfa51b4b8773511c1ca097a4d6d7f15b05d96ed7511e39aae51032fc3648c15eb4d789ce8916f79a78a1a0359eca8df24cd4ac526e7031b0b01f98b87f2be0fa5667e9596e96c212ed7d84a0987efc28985777345b301668a2208b099ac715f03bf56325fa874485859deed2a0278b5bef59d42d4013a3926c01c3c55bc3984951d0a51085f7db5dcc935ac7d6a04c35b4967661e70f5068aa326f3599c7393498e1b082b8b26062f98ffbb2e8f4a023d8b0cdfc5807cf338a56b1260118129ce2d1080dca624d02c1e7a44ef7255fa068665baa882f2e62da7897273881f510f3768c3d9878efdf097085ef3f0b5ac480a0d4524fcdca73a594f45be8e41613995cdd8bd38512c6932f04f6d6787ca4856380","0xf87180a05da0431ddcf9c0df5220e90991d6fafadcbb70ec9e51c042a743f4d1980df7c4a05e856a872504286cb6dbb11c85fab4ca263a72cbee0a785053fbbb4f2d6078738080808080a09922b3a2aac38c7bd2332ec05abd047f2fb7858f2d2ae4f6c49bce18b73eae948080808080808080","0xf8679e3860ace08b3156e1e8b3657a41748919bc942fd9e0f3de90d72f6e5bdfc3b846f8440180a0ee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0ba029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"address":"0x5f51e413581dd76759e9eed51e63d14c8d1379c8","balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0xee67942d4ba6f187e143ee4568896cf8db17df6298d91961b468176ef9e6ba0b","storageProof":[{"key":"0x0","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080","0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56307"],"value":"0x7"},{"key":"0x1","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a067c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"],"value":"0x67c02e5e272f9d6b4a33716614061dd298283f86351079ef903bf0d4410a44ea"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a02b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"],"value":"0x2b80cb1b568146d64e7a622d7b895925d06ef8582fa0166d8ec069f86070610a"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a00c2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"],"value":"0xc2f5e53902cca915645c2f00ae6a6357ce4aafa18140db4be24d33f41709b6e"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8b1a0f3ab6aa3f0575916e985798d7ee01e8c75436765f043cdfba2ad10f36b47f6d48080a069a129011ab4666f131c1bdac7d923dcbb6f1047057a62d6ecede5d17057658280a064bde28657cfaa21b487ad660da11e94a06a1b7f46502263094cde0407dfd24380808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd080a015cb29fd7064f1cbac8773177854799e563e10ba66e44c5adf25b31fa39a7d3980808080","0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a098d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"],"value":"0x98d7a1f953e0805e2053a6ab062f8a16f1d35b9fc7bad41fd10eece87cc1b280"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf85180a0fb829ab79f00d7bab5aa54e5cfd67ae721eaf17d076bca3984477a72b5391c92808080808080808080808080a0f7fc12e7aa12b24609029780c05d852e0ddb7e1eceaf8671a2e2d3c1aa7bd8068080","0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a079c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"],"value":"0x79c63d2302907690c944fa45f7405ac59b364089f366764025f13f2055511b43"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf891a031b20905ab02dba97c5a82079a50550a5a70d3f5e7f25cfe6c9e88b1c3768ae8808080808080a01b7ed3dd208fb30e8581d7e5278fb4581b99f960be8d08ff41759b10b537dfe080808080a03b77164a66693f214b5328da08b60566b0aeae3d719121004ed8c6d6e49ca5e580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf85180808080a0fe0a1c808c8e90225d5dcfad8bde23daee522b2905b605bc6eb5c39596018464808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0a7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"],"value":"0xa7b2aa99ebb2a9e076a84dfd43cc1355ca060aea5b8bb1f1ee825e131125e462"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e580","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8d1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e88080a028b34037d7d67765fa1cd15091337086eacdd8770b711a026d4ee0a839f8b3f2808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a0c9c743682962d9d06dd0f9ed6cb2620cce02f34a0a4f5d60a4e5d1e081a5b5fba0bf73b8437dc32850158814b8c0c28c9c76a22c373fa84a77c3fc2175317a6aa18080a0bd01265657739e1793ae1ad68a77f330e98f0d5d5a53235211faa848c3eea787808080","0xf843a0202f0f7a7af9ed4f160d1c425f37d148d10bddb9c828e99d4145b150485711cea1a0ac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"],"value":"0xac8d18ba63b2e8486a3c5bd9915b9335d0df0862e5601476fadf568443a8cca0"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e585","proof":["0xf90211a0b67c8fc9ccaf87362466a14c4714f75a7c9c006275629bd089e53bf8f6aef3e8a0bd9d8e083eb43f66f4d68a0380a3cd078c8545f824908c26ac5f07974738c92ba08bffccfd9d8731d2d99c8648802c7b5eff3fe744a2bc04379d6dabd1153e21afa036116c8887c0dc0123a4cf2245c15715e70b974258903b7356e4433b42f66680a0dcf55ed8f57d2c1b0f878e707eb0e97a569aa7ba7862c50ae77de4d1cc0b5821a00be8b340536029c2414fa57ba8e51d736ca4b65aad1b7a003b20302ccc93f7afa02d9e3c9a3e9c20257da776cc8f5ed75c1f9c6f9cf476de236151ced43b8cc8aaa0f73b2fa3dc8e174f3264edd2f919961667cae58a94261f583a6c6510a8dd563ba088e163fa4b0a1523f1c036041414d05bbacfaa6b936f30ab2e65f7a4eb3613aea0220f6d1822378bfbdfc6e22f95afd16d125e3c18ef03827558d6325f364280eaa0ae7d2d73044556135fc217f27b2872e1344c02141831190f71360e0c4336e172a0b500471bfcc9d941b168b2dcbad5f530b89504d913323fe8e64ec0fcf1c73d80a0b8a03827b3caf845deda97cd6494a368980b87a128a4da8749cc2170df171bf2a027b9fee8d3cfda74a3dc9b0dca2121790a7237fec5c3354367abc993a7255e68a095d48f902ec25c846ef66b4bed5f3863b34429b9383045b0200ad8a89ab77b3ca0cc4718b5f77c427bbc51c0971db6ebcc041b7c40cb7c90bc9f8262fb9792db5a80","0xf8f18080a03c79db405090818f0b5b51e29d2ac7b67f6ff814b03e773af1975584a0dd1f908080a0a26c5f90f028898be4e12961969ae89f323a66586730f92b8fb2dd1ca0ba6f8a80a078c9aaa17553d7357d2014c0a75c9de51fdab46248846ddf03ea16d8cb790b0e80a04a0c4b948805886065449dad60fce7e1c7680a3bc4a235800fbd2edafac731e680a0c50523b8a14aff442da2ba7343c04f960e59083796de9ba7fcbbd592959515f180a0df910adad94453538847b694bdb134432b0a9e2cc829dce2346460720fd2ee5380a06e1a723ced013021ff250a9fdd129c3a7c1aa3970d955cd28688dbdff277174880","0xf843a0207c73e826b7dd131777470492494a9f14b451e947ae119760ac27c5aac4422ca1a01fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"],"value":"0x1fae1104ad418c61c2e19407f6151fa634431da77d15469ffd1b993986fccc59"}]}},"signatures":[{"blockHash":"0x5c5e93b9565f27fd2323e0ff8e4223544bafae7901471add70020a096ec8dee0","block":2561644,"r":"0xdb56478244ca51fa117f59ee2379748b91021640b466712b7b750c4ca9a214da","s":"0x318ee91d84427a8c8b0df9a2bf19d8dc9335b3ab5929133c35ccd961f0eb00c9","v":28,"msgHash":"0xec3e451ce1509cac55e9354fedbc5a73ba3da6cb0671d94e49afe1c4f14ae270"},{"blockHash":"0x5c5e93b9565f27fd2323e0ff8e4223544bafae7901471add70020a096ec8dee0","block":2561644,"r":"0xe23964ba4e0d19262878f3cc37b85c059f7622d4be1e1f4a8bcadb61612f223f","s":"0x0be2645b020d53e1bb57dafe52692b54b4b7cf69bdb41270a21399dc4a704926","v":28,"msgHash":"0xec3e451ce1509cac55e9354fedbc5a73ba3da6cb0671d94e49afe1c4f14ae270"}]}}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/kovan/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226748,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226772,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226796,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226816,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226836,"weight":2000}],"contract":"0x4c396dcf50ac396e5fdea18163251699b5fcca25","registryId":"0x92eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf","lastBlockNumber":18098311,"totalServers":5},"jsonrpc":"2.0","in3":{"execTime":76,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90245a091c685f52558f94367065f640ab0c7c17853216309e1cada3c342b87a57e733aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794596e8221a30bfe6e7eff67fee664a01c73ba3c56a0e344998e6528aaf30b97207d1b2e2dafeae87f8f8f133bb66218a354a90ace47a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe84011428888398968080845ea100d49fde830206088f5061726974792d457468657265756d86312e34302e30826c698417a84035b841cd1f64190b9508e3b7cf6ace0a57e837de0ea46302a13d64a22920e98540de355505e0bb74053602f5909b2ed59ecc431e2fadbdbd5bf8bf1fc805593e58507101","accounts":{"0x4c396dcf50ac396e5fdea18163251699b5fcca25":{"accountProof":["0xf90211a0a45b8876be09fa1d9d747b5989724cc3fe2ce30451174e4cc659e513e966febfa0ccbc55a9cbe4436094f01dcf0520b59f1c4460d3438439064eecfe5718fc3091a0ace597c6dc1592ac645cf485a91fc0f4a4bcea188c7199447380f608b6fa5ef0a0223db0b8c5bbc7c1ea17372ee82dcab1e1e8a661df1bd27b76aaf7c5ffb0598ca0a31dc648ff5a14aa545ccbd3220b27ae386ea8dec3fd9f8844d1becd04163aeaa0dbeb172d754ebaa5108409a4ba7b404ed9654d03038cdb46cf1179698f83170ca0a5e0b815a0dee273e7f899f2faf1c9b827e55161baeb3921bd48d9d21175c7d8a07d176a5244bc310bad8bb3af64d67ec68b460ee8ac1dfbba3ff0b296dcd92382a0f6acf775f557b4ce053a7a6f4667743357f3e4499fcc9b0f620d2ef238efd4aea028e4dfed3b60360ba3babfac5a87cbfa749cad3d4ade34f419b8c03fe3924634a0c69d195606b711b5a17892e1167b8b374ad4ffbe10221fe538cc8b4f4d1f5087a01f4fdf8d13e311cf3b9679eab4f0b0d699855183f3680ccd88a43cccfc34e44ca08649077b37f2533081111fec1b398356e08472f0af4e0c99253e861a53e50792a04c251bab455c4a30bc50801b705260cf25ecd550832e0402a86c220c35e52f54a00ab06f83b19c244fa84f732de90e31764849df98f08270f75288656b82528c29a05736631da0f019200a950d3c5d8070feacbd4c8efdf58a9f21205160ec8a9dde80","0xf90211a090bbc8ac3680c2ddfeb5878a399aafec04050f25b44a38f80b2f8c0f50850a2da0d4d90af016c72ceee5d9a0fd232ba64e86d92b469d52e02a3f5fe8c8c0c4b7a8a06c2378d8b23f5257ecbe90e20a25fc8e83d23fea051d096bf0b1b28ba025f29da08f85e174fe63f730153fa6acd822c540b2924d87e37ff07842ad3d7ac35521dfa00f70401b0be62447c8a25c00305763d5aa85c79101d9a985231f5cdb6701fd8ba0e713e5f9159ef8694955d55099221982ad06f3636645b09636d1e978c1ed777aa0fbe136e564a86068540ec1c15795b19ebf3eb9d159b1346d8cc2f6fd5174acb7a035a6a4480292efcc53b1de6f79811f5fad898e34ddf44d818ce9f1b9d1a33821a0edcb871b14dbc51f1efabd72c0fb1085e9682c692d217e9a5aa906538f5e780ba07d529ff5896c14b6f5d2b84c4323fa5fb4199a32567e7b3ca1fabd98b424b42fa0dbccd5b36c4b6551234bad08c1b9dda1f05202febd803a49e43eda2f82d6e2afa070a2fadae7d05be1c95fce65120427f264fdb80faace4f2db67365fe05c88d55a08967bc5d2112795c54333b2c620113e2f47b99d933096dafbc7ff56a60dca4dca0af9a8d9f5d541fce4464737344173d8a7efce510165b7f50b84379b797dd78f8a03ee1f38e364f17cef7ec0c03b4638a5439f0b27918e0f461f30463d48e4dfa94a0c944bff64c831f51542a355b8f8784946c8dba3f5e07b49979d4e3979d8db91780","0xf90211a0ff0832e8c3caf7da0b6c72a9737f0d746780dc89c577aa89d2b39eb6b9da1007a0afed4332114c8f69e7701896fffe92347cfb999a69839e93a8609f36ba753486a0ead52c1742413a873a506b5a81314cbc761700fb7f467bcecca767027343c55ea0cd2860a819e1266d6dd4647dc024db1d9bd017f0617c319ea005fd41a7d9701fa06d99b8958500ac421b6ef8a199739171b8e0c4481de65d5e4597c67202209920a0a8198fcd3bad261be90845b9f80b721d9f8112833c4ef91a42563c6a2bab2d54a089aed0060440c5ff271521e4cadbdaf9f059286a7b2fd70958977a2013a9193ea02ea4259eb2cee670084d7bea49ae1107936ed96cd220629b53595b952e3ac721a01c8a6a54af967c76f004f22da9d99e46b952f6a461e4ec425e847d7d174cfaa2a047b4497835b8e52065f3b92287a1532cfe4fdcc8a48f1d3d232588c415f58018a08e89e985d74ed22cecb6af86e87eaf0ea5aae809d7fee4c5014d3e5b13085b30a071f47a364b8a0fbed8df2d753d918e8a59b8509ef4bf7568dfb5a83e5c7599fda0409400d6d171d34943576600f904ff8596ddd374b5f6b8ccc64727ae0ed10724a0146721c13efc926ab0f6e4991ede8161eb87b67fa70e6dfccad3018cb8b925bba0c968190bc6bd0f154288ec9271beae9c4f421797e46961141b852e9cc311d884a0d6f2d559ec41be463bac8d8a1b281c489b0308e3b212b9060292585ae046a1b080","0xf90211a0031b7c18f8e7f4b4cf2e405b07ea3dbc195cf53d8696b0b27e70684656bec085a0f8a9556ecf920a7234a0a8f560de8bd6e61466e8b9274e90ace7df4704504949a0922be1e7c4e0ec0d44a600ab10794baa5e37c062c58eae1c3927a2c4307ec368a09272b082a1c94433661d1b7d74c1b763b97a63b582da5fbb83f2fd6acb860b07a0deedea2d9f52972563b496d91f0f2ee0ae91d81a0f2e22cd19c9ebf4874f17e9a01f234ea7b0895b70808061cf3ed83ca1af25d2580b4940ef98e8035297c31408a090938b0aadcff6edf0ddf6126991975d8bb74d04dc4493d280c09778101330e6a0b84803dd8961c537cfdc8f61b6f682aba5a5399f6f26e0cb0e3600f75cd13ef3a0d0d61f26ee25c31946d495c4281e4f159a2824538af94b64a8fc5612769bd317a0b9e421a8b60c298fbcaa080dbd2a7542e4012adab74d5aa95b2f0b6a062cee9fa05a63d3fdca70151e6f068ea04621e68f9a8e917f084a554432aa21d6b0d16079a095bfe74f88bad1d51ac8466a062010b2d9f32530835c2f4832a4e75515375fcca07410370671c4a964aa56978529333439a5c9a2cc09920a763eb5eede96ee603ea078da909c0f5e9ad29104d6129bd43c125cba59be7af2bdb9e76381296dc33a16a0d8ee6980d88fbb783779c904627a9324e8aec730cae4dbd6cdfde11181b901daa0d86ca9182d02ebb63138806592ad5ee14ec67125a4ba8e218607315ae98735f980","0xf90211a0d6ab14b59da8c3fb515d74535cef24b4359da840e37f513df7ff982903789035a0fbc383faa9b10a43db4d09f58ed08dfff56a2de1be2dff5842fc0ffd9d5b951ca0f08dbb2b9793b65209341462efdfbcf8bd7e78d7e76665a1b95554f23dcaf426a0410748d04d6939083ebd4aed7c3cef776c9252b8443fc9ef884ad0f31e45e5fda040de2cccdd265989c9eb20f7195754156151ae8fbeaa563fedf8b340762929aaa03f8c87cf5fcd963079355d7861535a527481a04cd13d5ca3b1ad5e7f9cdf1dcea0f81cccec2a9b8af796d87f5039f1e881af477de2226bf149d5f3ae76fe5da254a0ecb8f2e60f7c83dc0cd633b9e2a1af98201b73ce12ee8a7ed25f1706963561b1a087e852ad709db6e12898cc78a671f74235e748b0e06f93a32f1c749f01dc0dfca0af57a4fb8694e2ca0d40d8cc898b7a87772525309d8f4145201a1500d6123328a04f948f48e67cd3d5f6696c2a7909694bd62919b40f6a85a1c0f473a2ada6aec4a0f7ba2d0b7acd3f92e5410b3060fefd920230efdf5623fddf5b9fea3242b4b6a9a06e55b7b3de07096ad947026aece42593233ca2c55934ed1086402c01dfeb474da0791b1eff2e2c6bf280758fba2266379c53b86924c3aa2c0c7774eeaca046517aa0264c9317a0c0dc902bd13f2590633c365463ffd7b618370292d51b910e494048a0f17b032902d635eb802c85eeb93398a0f6c718cc063d8bc14d265811501127fe80","0xf8679e3ff76b4fb96a84d0c4f946d824a53e915dd63f83eb5bab6090247f03ccf3b846f8440180a0a7936d5bf9e87688f4ca47f7b7ce7279bcba19f0c6f3a10b4656b63c227b51faa029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"address":"0x4c396dcf50ac396e5fdea18163251699b5fcca25","balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0xa7936d5bf9e87688f4ca47f7b7ce7279bcba19f0c6f3a10b4656b63c227b51fa","storageProof":[{"key":"0x0","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf8b1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e8808080808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a081b7693d9ef9dea4b83b27e12fd4a86cfd861c266865545c3602ec6a1e43039da0ef62f9931a4433273c75721a7b9baa85cf48dfba6768d2f23f64b745e6cef462808080a01b1798520b0c4957cb27fa3e651e6cd8c5fc59ef1affec35260171dbb38dae8f8080","0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56305"],"value":"0x5"},{"key":"0x1","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf85180a075cce7489bf591ec2f90155e92efda2ef53f5bac10f2af1bc5c01f6d77eb47d7808080808080808080808080a0febeea5cc749da1d093391d9849a0b20905212b9458732ad1da5347bd23e01628080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a092eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf"],"value":"0x92eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf871a050a31c247b23c6417077ca2198776fff2f9d3262fd091aebc9d9233cc140625b8080808080808080808080a08c9bae9aa669ec1c34b704dbe972fdd9c3e9d1223ade5ef3e24d0f38466b786580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a0c2bc5844ee95f17993d2b2de96f318e09fa9df683ab14a8050163c19ab0bd28c"],"value":"0xc2bc5844ee95f17993d2b2de96f318e09fa9df683ab14a8050163c19ab0bd28c"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf8b18080a004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a06d32ffd67e2fccef0fa97c367d7a596d64bcae9ea664c99f9aca4c82f4092ded808080a0831355ca963d9764e261257fe2cdba0652d7a6e3df99643b5a7650fa5d19393180a06f1dc9175cce4ec8d36fb5486ce816c233eb25f7f97c7fec50d0fce43dd8515880a02178df9358718320ce28edcc87547f683682fb5513f4d6bb0b21f7fba1b56b69808080","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a072a8826c6e484b4e97ffa5cdf8fc38c40fff346f9df357f3116791b480d19c58"],"value":"0x72a8826c6e484b4e97ffa5cdf8fc38c40fff346f9df357f3116791b480d19c58"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf891a0bd86f2f34009679b0f4d3f522f439e4934e84fe913c966c38c00792282f3e0568080a09c35420d660d199ac9631244dfc473cbe95de804f53ba3ba0c59b0632eb3990a808080808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd0a01c52ca1593307ac4e343ecda9916ba7b7102704404f4efd3619d31c7871dc80a8080808080","0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a06a5906723a592d65850ac9d0c8a930f69187b56e5d14107df20dea58e7ad7d22"],"value":"0x6a5906723a592d65850ac9d0c8a930f69187b56e5d14107df20dea58e7ad7d22"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf85180a075cce7489bf591ec2f90155e92efda2ef53f5bac10f2af1bc5c01f6d77eb47d7808080808080808080808080a0febeea5cc749da1d093391d9849a0b20905212b9458732ad1da5347bd23e01628080","0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a0983a0d7d7c66d19b7ab12619841b6d16ab15c27ebfd441c5b137f55f3653f572"],"value":"0x983a0d7d7c66d19b7ab12619841b6d16ab15c27ebfd441c5b137f55f3653f572"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf871a050a31c247b23c6417077ca2198776fff2f9d3262fd091aebc9d9233cc140625b8080808080808080808080a08c9bae9aa669ec1c34b704dbe972fdd9c3e9d1223ade5ef3e24d0f38466b786580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf85180808080a0e1f7830233096052067e622b9f27023711865d60e03f79a918c17ac0c503aae6808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0081edf7d686676aa4746506c37c581f01cb056f27ddd80cd8f7782d1b8649a26"],"value":"0x81edf7d686676aa4746506c37c581f01cb056f27ddd80cd8f7782d1b8649a26"}]}},"signatures":[{"blockHash":"0x7dfd009a2e4a242240151984fcdb7b9f5783c929c592b61a738b24493034c4bb","block":18098312,"r":"0x42431db3421d0b728a2471275527604957c491f37ae5bc534369a01c74a86e1d","s":"0x440ae8c33dc7f502dd87b9b8f7c2e318bbdc835e977a159786b8d71e2e3e0b30","v":27,"msgHash":"0x5ea8176a6eadd13997304d0144791c36e4ca7390878e1ef881d24fe4423dbe38"},{"blockHash":"0x7dfd009a2e4a242240151984fcdb7b9f5783c929c592b61a738b24493034c4bb","block":18098312,"r":"0xd9d7ea6a801b3b473d15ab6e15199327e8bf3884aed274499f2417fe76bef020","s":"0x301e4b4cb237725d30cc5ba7ac29bc2bb9bbe7b01d6e2d7c7db91a83471d0fc6","v":27,"msgHash":"0x5ea8176a6eadd13997304d0144791c36e4ca7390878e1ef881d24fe4423dbe38"}]}}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"id":1,"result":{"nodes":[{"url":"https://in3-v2.slock.it/kovan/nd-1","address":"0x45d45e6ff99e6c34a235d263965910298985fcfe","index":0,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226748,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-2","address":"0x1fe2e9bf29aa1938859af64c413361227d04059a","index":1,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226772,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-3","address":"0x945f75c0408c0026a3cd204d36f5e47745182fd4","index":2,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226796,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-4","address":"0xc513a534de5a9d3f413152c41b09bd8116237fc8","index":3,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226816,"weight":2000},{"url":"https://in3-v2.slock.it/kovan/nd-5","address":"0xbcdf4e3e90cc7288b578329efd7bcc90655148d2","index":4,"deposit":"0x2386f26fc10000","props":"0x1dd","timeout":3456000,"registerTime":1576226836,"weight":2000}],"contract":"0x4c396dcf50ac396e5fdea18163251699b5fcca25","registryId":"0x92eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf","lastBlockNumber":18060209,"totalServers":5},"jsonrpc":"2.0","in3":{"execTime":74,"lastValidatorChange":0,"proof":{"type":"accountProof","block":"0xf90247a087986ab458affb5be989d38ad1533abfbe759baf07a871579592e480cbc5148aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794596e8221a30bfe6e7eff67fee664a01c73ba3c56a02690ff523f5551f51730f2cb3712a25fbd72c5551ee1d31bf74cef98f9d45fd9a0d5b48d833d013e4efa89b1890777ee77010be36b07bde9dad50ca4e165725181a0fbe963864c3abd9f03d7d698b6c323c74a228ce178c4744c072ee467d4a723e7b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000010000004000000000000000000000000000000000000000000000000000000000000000000100002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000090fffffffffffffffffffffffffffffffe84011393b183989680829b30845e9eabe09fde830206088f5061726974792d457468657265756d86312e34302e30826c698417a7aaf8b8413bb0acf7d2e70dcf3769dda2f2a025092fe54cce4ef345e5f6ac141b4111f6fe0dd8aed16d486994284b1d31d8a1ec91377d45b12e72761d05f39c1c6996a24a01","accounts":{"0x4c396dcf50ac396e5fdea18163251699b5fcca25":{"accountProof":["0xf90211a0690497c203b65f38faf258d7bf2cdd47c00c1e5ec220b3eab2e983c8fd9c86f4a073c038701d43401b74e6ff32184fda7718dea20f0e988e022153612e39f5be29a02a8881a4448fa05b60e07718b55e6523edf40cffef1805504c7d7415fc7c2f26a02ac1e292a86f71c438804b452e1de699439ee4297646120a140412390c199cd0a073c4b17b8f847df8246315186beed80c2708f736091cb75b4a655d0f0e4c0c6da0e7f71d100db3f858fa516dfde39dc91fd4d67b6b5b252472be5ddc17303e7058a04d4a07dffd1ce950be0016c98b510ba8815b562041d189547f11605b15aab26aa0cb339feae53c14c9431ceb6db2131062024eb54536bbedca5ed28fd9259a8b6aa0fb7ebe80ab4163734e539df3a4c6c55311ae3f3ccd3265bbb89561f92b76c2b7a0e058582d0883447f4171cd31061ac810231f42b7b001495536f8e05b6df4f9eea0242f8f0bce2f5b03ef3adbd4b4287dac473d514f3d7a28b514a4b96ad9a15afea0dd9f6c89141caf0cd5b13ced0d554471d6a41f72b66ca53e812878f1626a45e0a01f9fc94a2f70c8dbb9e758388c36c39786e43b7a5f89d5209f0bf0d614646864a054008ffeeff2b8334621c6cd5a3934e033d36decbb7205f812ad91a60b645defa04421ccf295955b036547c714e27185dbcec76cd10f48eac21518c7a2a73b0dfda008029b245df8def566467dfb7e8ea1e30aa8ae4ed03cd8f3088f92cc7d9c323180","0xf90211a0cc92a84ccc6e0ec0d55a914ef00fb7fe08a978da66eaed5be4181b7f4f7ce438a095f73ba162a6ae45c7dfd88c58158b5b454ce9981d8130a713300f6ae6781204a0311c203d5f0537896685165047e536ab993900e95eaeaf46d4ef70a92b99464ba0fcc2e46a29c8de2cd79d0c2ca4b958a2e302906d02a47eb3723202caad12a01ca0b1533be7738a71e96be7b83e06d5385690d5023f1eb583207206ffb4fb530164a0e9ba690bee2fcc938bdf1699d3426b642fc513a2ee77347a0e566c278fdf64d3a0f4474057e2636248f39ed2b2eff83c7b67e06e817fbec0688bc85aefdc8234d2a06ecf43cee271cc5ca763483a1d86c9281abe9e958e856313233ee71c6c7a70a6a084ce32ffce5704eb3e635a11b62f6cdf9382333633b41e705bc64e357dc73eb1a0c3cc9921f0716c6170489567b6f49cd541e196e728db788a9b99ca198eb4b028a071403920d02f6f7e807a5272c79069326803b36f8f0c1c14980849efc4d3117da005cb1e35359fe9aac2f028cd3c4ea3f58e188530f2225464077a89f0aa9f15bda0025ae763fcb9168599738137a30d99311727bfc02508347692573e9369d2a814a0188c123062ccb525051a153d8927f76aa21b9d39206f0a4df14e619da9399aeea0d0bdfef41ab26631344b9f0075e063df6d547158e2ac8f19d5b4950ab761b57da0f7bba90ec83f5c3c2b0910f3026412c1f588a9fe05a2935f5590cbbf6f1c91fb80","0xf90211a0ff0832e8c3caf7da0b6c72a9737f0d746780dc89c577aa89d2b39eb6b9da1007a051853de8c922d34fd262f0a4d46085b877878d717be71aa1b61ca6d8fb0014eea014bd1f52d05cc57a49024a4133a4f69fd0fcf667e9662cfc60eff5a5e40a8cc9a0cd2860a819e1266d6dd4647dc024db1d9bd017f0617c319ea005fd41a7d9701fa06d99b8958500ac421b6ef8a199739171b8e0c4481de65d5e4597c67202209920a0837062b378283651a90450b1c186aa2478f4e070c1d10c092ab68e5252564eaaa089aed0060440c5ff271521e4cadbdaf9f059286a7b2fd70958977a2013a9193ea02ea4259eb2cee670084d7bea49ae1107936ed96cd220629b53595b952e3ac721a0dc617efeac98b003fb5c3bb8ebd32964591039be6e5de91a49088936d84cbf4fa0f4d53f1ca02e51aa67fb1b37ae57a21e85bcac7d2e74f663495c0ac3754f4f8ba08e89e985d74ed22cecb6af86e87eaf0ea5aae809d7fee4c5014d3e5b13085b30a06742d96d198f6426d623f160d1a9602330f06cc52b66a0d8feb0645c444b4714a069934e8cf7ab41e7231d635e57b3839f4c8129dea75e26455e936b17802a5b2ea0146721c13efc926ab0f6e4991ede8161eb87b67fa70e6dfccad3018cb8b925bba078a361819b563dfee2e18968205beebc6b8de8bfb03d92ad352357fa22f82518a0d6f2d559ec41be463bac8d8a1b281c489b0308e3b212b9060292585ae046a1b080","0xf90211a0031b7c18f8e7f4b4cf2e405b07ea3dbc195cf53d8696b0b27e70684656bec085a0f8a9556ecf920a7234a0a8f560de8bd6e61466e8b9274e90ace7df4704504949a0922be1e7c4e0ec0d44a600ab10794baa5e37c062c58eae1c3927a2c4307ec368a09272b082a1c94433661d1b7d74c1b763b97a63b582da5fbb83f2fd6acb860b07a0deedea2d9f52972563b496d91f0f2ee0ae91d81a0f2e22cd19c9ebf4874f17e9a01f234ea7b0895b70808061cf3ed83ca1af25d2580b4940ef98e8035297c31408a090938b0aadcff6edf0ddf6126991975d8bb74d04dc4493d280c09778101330e6a0b84803dd8961c537cfdc8f61b6f682aba5a5399f6f26e0cb0e3600f75cd13ef3a0d0d61f26ee25c31946d495c4281e4f159a2824538af94b64a8fc5612769bd317a0b9e421a8b60c298fbcaa080dbd2a7542e4012adab74d5aa95b2f0b6a062cee9fa05a63d3fdca70151e6f068ea04621e68f9a8e917f084a554432aa21d6b0d16079a095bfe74f88bad1d51ac8466a062010b2d9f32530835c2f4832a4e75515375fcca07410370671c4a964aa56978529333439a5c9a2cc09920a763eb5eede96ee603ea078da909c0f5e9ad29104d6129bd43c125cba59be7af2bdb9e76381296dc33a16a0d8ee6980d88fbb783779c904627a9324e8aec730cae4dbd6cdfde11181b901daa0d86ca9182d02ebb63138806592ad5ee14ec67125a4ba8e218607315ae98735f980","0xf90211a0d6ab14b59da8c3fb515d74535cef24b4359da840e37f513df7ff982903789035a0fbc383faa9b10a43db4d09f58ed08dfff56a2de1be2dff5842fc0ffd9d5b951ca0f08dbb2b9793b65209341462efdfbcf8bd7e78d7e76665a1b95554f23dcaf426a0410748d04d6939083ebd4aed7c3cef776c9252b8443fc9ef884ad0f31e45e5fda040de2cccdd265989c9eb20f7195754156151ae8fbeaa563fedf8b340762929aaa03f8c87cf5fcd963079355d7861535a527481a04cd13d5ca3b1ad5e7f9cdf1dcea0f81cccec2a9b8af796d87f5039f1e881af477de2226bf149d5f3ae76fe5da254a0ecb8f2e60f7c83dc0cd633b9e2a1af98201b73ce12ee8a7ed25f1706963561b1a087e852ad709db6e12898cc78a671f74235e748b0e06f93a32f1c749f01dc0dfca0af57a4fb8694e2ca0d40d8cc898b7a87772525309d8f4145201a1500d6123328a04f948f48e67cd3d5f6696c2a7909694bd62919b40f6a85a1c0f473a2ada6aec4a0f7ba2d0b7acd3f92e5410b3060fefd920230efdf5623fddf5b9fea3242b4b6a9a06e55b7b3de07096ad947026aece42593233ca2c55934ed1086402c01dfeb474da0791b1eff2e2c6bf280758fba2266379c53b86924c3aa2c0c7774eeaca046517aa0264c9317a0c0dc902bd13f2590633c365463ffd7b618370292d51b910e494048a0f17b032902d635eb802c85eeb93398a0f6c718cc063d8bc14d265811501127fe80","0xf8679e3ff76b4fb96a84d0c4f946d824a53e915dd63f83eb5bab6090247f03ccf3b846f8440180a0a7936d5bf9e87688f4ca47f7b7ce7279bcba19f0c6f3a10b4656b63c227b51faa029140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1"],"address":"0x4c396dcf50ac396e5fdea18163251699b5fcca25","balance":"0x0","codeHash":"0x29140efcd5358d1dd75badfaa179e3df0dd53f17a883a30152d82903305697a1","nonce":"0x1","storageHash":"0xa7936d5bf9e87688f4ca47f7b7ce7279bcba19f0c6f3a10b4656b63c227b51fa","storageProof":[{"key":"0x0","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf8b1a0f881becd1a54ec2ac129979fbb7cc851f4245d372d588056b040ccae152793e8808080808080a0f229214dba34c16ca65b1e0df175282a07b3ea9453d97f5b9e9e78762fe279fd80a081b7693d9ef9dea4b83b27e12fd4a86cfd861c266865545c3602ec6a1e43039da0ef62f9931a4433273c75721a7b9baa85cf48dfba6768d2f23f64b745e6cef462808080a01b1798520b0c4957cb27fa3e651e6cd8c5fc59ef1affec35260171dbb38dae8f8080","0xe2a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56305"],"value":"0x5"},{"key":"0x1","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf85180a075cce7489bf591ec2f90155e92efda2ef53f5bac10f2af1bc5c01f6d77eb47d7808080808080808080808080a0febeea5cc749da1d093391d9849a0b20905212b9458732ad1da5347bd23e01628080","0xf843a0200e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a1a092eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf"],"value":"0x92eb6ad5ed9068a24c1c85276cd7eb11eda1e8c50b17fbaffaf3e8396df4becf"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e567","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf871a050a31c247b23c6417077ca2198776fff2f9d3262fd091aebc9d9233cc140625b8080808080808080808080a08c9bae9aa669ec1c34b704dbe972fdd9c3e9d1223ade5ef3e24d0f38466b786580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf843a020418048a637d1641c6d732dd38174732bbf7b47a1cf6d5f65895384518b07d9a1a0c2bc5844ee95f17993d2b2de96f318e09fa9df683ab14a8050163c19ab0bd28c"],"value":"0xc2bc5844ee95f17993d2b2de96f318e09fa9df683ab14a8050163c19ab0bd28c"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56c","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf8b18080a004086d122b3bd8d29156e97aacb81408ae87858145b9749f8f6c7bbf653d6ce38080a06d32ffd67e2fccef0fa97c367d7a596d64bcae9ea664c99f9aca4c82f4092ded808080a0831355ca963d9764e261257fe2cdba0652d7a6e3df99643b5a7650fa5d19393180a06f1dc9175cce4ec8d36fb5486ce816c233eb25f7f97c7fec50d0fce43dd8515880a02178df9358718320ce28edcc87547f683682fb5513f4d6bb0b21f7fba1b56b69808080","0xf843a0205fcc8f73196524ea5f04c38888c2f09c6cbef411cb31e259d35b56e3d0047ba1a072a8826c6e484b4e97ffa5cdf8fc38c40fff346f9df357f3116791b480d19c58"],"value":"0x72a8826c6e484b4e97ffa5cdf8fc38c40fff346f9df357f3116791b480d19c58"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e571","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf891a0bd86f2f34009679b0f4d3f522f439e4934e84fe913c966c38c00792282f3e0568080a09c35420d660d199ac9631244dfc473cbe95de804f53ba3ba0c59b0632eb3990a808080808080a04a5be21f4f0c0f5e1fcccb140e7cb5b1ff2ce45bce977d8e23cc7320e8c7bdd0a01c52ca1593307ac4e343ecda9916ba7b7102704404f4efd3619d31c7871dc80a8080808080","0xf843a0206695c256a4a4a1b8ed004dc824e330f1747032632c0e6d88c1d84c330c1c5ca1a06a5906723a592d65850ac9d0c8a930f69187b56e5d14107df20dea58e7ad7d22"],"value":"0x6a5906723a592d65850ac9d0c8a930f69187b56e5d14107df20dea58e7ad7d22"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e576","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf85180a075cce7489bf591ec2f90155e92efda2ef53f5bac10f2af1bc5c01f6d77eb47d7808080808080808080808080a0febeea5cc749da1d093391d9849a0b20905212b9458732ad1da5347bd23e01628080","0xf843a020257165ee8c7eae64faf81e97823d50dba1b6a2be88bccea1ac5d01256f0590a1a0983a0d7d7c66d19b7ab12619841b6d16ab15c27ebfd441c5b137f55f3653f572"],"value":"0x983a0d7d7c66d19b7ab12619841b6d16ab15c27ebfd441c5b137f55f3653f572"},{"key":"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e57b","proof":["0xf90211a00d386a380f4989f679d9cf5d9ecfae5c5b35c2db02f0fbc39a451d5dc63e45c6a0c99c4dafe5edcf236f2c801b56512abe264ba3be39e258f82b8a8f73fa761c89a0b922b1c3cd45bb92c006a63d00f59097ff2febf76a229e47bba0fddc01b0c7b2a0d20e8512b5c211e7418412e720c749026ba65c0461b91e0bb3d5e37d6601e21ca02eccaf8a1e3e19f6b4f1d19682584db5a65fe33aef029b614c17a844fd0c8275a08c21490071c1456549ea87619fd93113532b72ef74959189a95dad817d673271a0b01cee6350cf6284fe93d9c2e56beb0d4fa0272b9f1c6a391fdfc4b037635709a0551dffaed38a34bc397189e9f3fd07181ac5d9fe284dbad00bfcf6be297fc92fa077d88f6269b464eee1c499c2f0b0f02e154bd96819de005186101b6b6907a3f1a08576f2482582e4e6dda6f02d5bf8d5ff352cf5b7d73bb0e2c766d7482b7643fba0b115727736b9264675ffdd758a541f6632b8a6407281dd2339ab357e27b6ed44a0b20bc99ccd7a4318d26f785976b27c807f6b3a388b1005f07c8d177f9b28c297a06d22a544d3dbd8a0de38b4adeecdc62393bbe8acc51550756eade1b6f359f294a09b9229b8f8618c9801b139d79a8e3f5c1f575f250af0a0b43f54f5614313f4ada09098856655fd6f83f7d0ae3a1d24df2bb31aa1cfe9719419d99bbd1e29931904a01d6cc819b88e2433c90c9990aed9dc37c67c80729c88d583c96832b368b76d9b80","0xf871a050a31c247b23c6417077ca2198776fff2f9d3262fd091aebc9d9233cc140625b8080808080808080808080a08c9bae9aa669ec1c34b704dbe972fdd9c3e9d1223ade5ef3e24d0f38466b786580a0a3e90ff33462c5a993a90a3387e5c9c2d7aad2f327ff5c69cbfab2e5ce6c3a798080","0xf85180808080a0e1f7830233096052067e622b9f27023711865d60e03f79a918c17ac0c503aae6808080808080808080a04083c8127572e64ae53476470e7a632258565a37b7f2066cb22ef228e679c24e8080","0xf8429f3d807394a26a5623e844d859daa1940d13cb7bda091582294562d688f4de00a1a0081edf7d686676aa4746506c37c581f01cb056f27ddd80cd8f7782d1b8649a26"],"value":"0x81edf7d686676aa4746506c37c581f01cb056f27ddd80cd8f7782d1b8649a26"}]}},"signatures":[{"blockHash":"0x959f4b5c0211c94a308c0f714ad45200588348988b0f597ac17c51287f418090","block":18060209,"r":"0xf91e053f4b926bc703cb14614f33b510360f72bd3d5d2870e5a4286e01dc4072","s":"0x61a05da939c14e336bc916ac57ed6b2e7fb82ae334d0b8e46ace3962156d80d9","v":28,"msgHash":"0x5e07b25f615b1af1e824f20f00ad4621b7d1c2776911567d182979161d497706"},{"blockHash":"0x959f4b5c0211c94a308c0f714ad45200588348988b0f597ac17c51287f418090","block":18060209,"r":"0xe49158b597b21967a34e828a4e2656fb1e5ce6d177ce299a5d8010013013b273","s":"0x6c1e2d906d10fe8b2ff1ec7951db308ba8e0167abef0d4d86914fa70898f96af","v":28,"msgHash":"0x5e07b25f615b1af1e824f20f00ad4621b7d1c2776911567d182979161d497706"}]}}}]',
+ },
+ "eth_blockNumber": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":"0x97a142","in3":{"lastValidatorChange":0,"lastNodeList":9936896,"execTime":90,"rpcTime":89,"rpcCount":1,"currentBlock":9937217,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":"0x97a144","in3":{"lastValidatorChange":0,"lastNodeList":9936729,"execTime":634,"rpcTime":632,"rpcCount":1,"currentBlock":9937220,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x2764d7","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561645,"execTime":32,"rpcTime":32,"rpcCount":1,"currentBlock":2581719,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":"0x2764d9","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561644,"execTime":40,"rpcTime":40,"rpcCount":1,"currentBlock":2581721,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":"0x114b8c1","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18098311,"execTime":95,"rpcTime":95,"rpcCount":1,"currentBlock":18135233,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":"0x114b8c9","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18060209,"execTime":55,"rpcTime":55,"rpcCount":1,"currentBlock":18135240,"version":"2.1.0"}}]',
+ },
+ "eth_getBlockByNumber": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":{"author":"0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c","difficulty":"0x7f342050eb05c","extraData":"0x737061726b706f6f6c2d6574682d636e2d687a31","gasLimit":"0x98961e","gasUsed":"0x985344","hash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","logsBloom":"0xd46459b901035b09020172406000521420cd1102069010580501a9423a2a840204188330d1300a000090a5f4a3230b145280951b2808064180209e82756e562867626ec0861c45186884cd4b05007b3aa88280ce8a052482140a06ad077c7209da2103c0023804cac010e1a81dab0a093ea8725a84a629002ab03d3522a107612c0450404164801ea92f8668b7020a6d0c0c85400d84256200c1c89a4a360c548f4ee99100402d450d23439601fc9802d0ce088da44bc17000eb04931cd6535e275a432209d04460259250406422675428095336e898240180240091324478042890a02cb192d00c301288b4680c74b41a046042c8882a82680095281f93e87a","miner":"0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c","mixHash":"0x7116e0d21839194324c008c7a63d5f039bddb9f46423298fe8872291d4857504","nonce":"0xa6702fc00021d7fb","number":"0x97a142","parentHash":"0xcecddcdc0a45a9f143aa1c512e6b730d6747d8947f53d56df255c35f2504e042","receiptsRoot":"0x96518f4bae284a23f124f289f1bcf206b2ac04e8b244ade5387d6de36e62a857","sealFields":["0xa07116e0d21839194324c008c7a63d5f039bddb9f46423298fe8872291d4857504","0x88a6702fc00021d7fb"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x896a","stateRoot":"0x8a1c0af419b0ecf35688627b63cd4523629c737b465f203c2df17ad4c7561d31","timestamp":"0x5ea34392","totalDifficulty":"0x3344cc1c9237e34865a","transactions":["0xda4d70657451e1d3bbccd7308618437a4bd8656f04b999afcd834e4b347ca98a","0x0d380bda311c1031a8accc15b28f75e124b822d0de4e19000a10187fc2c1d24f","0xd7fe9eb19c36d12ce7586edcd483000d9865ccf4d0f25c8c90cb6580baccde27","0xe85325aee703f102edf9739049aca75101165193f9b7c6b4bca81651adcf3f9e","0xeb358c899c0c35fc352c749dd09a6c433c3fbea96d60d3c07fb7f1c930208707","0x37254c2c66808a320c74dac5ae8952a3eebd0e5b2f77ed46f2eaccd76b0d8e9b","0xae64e108af0cb862a77f29bc9ade51863291144922b1d21366871a159b6529d9","0x2d1b323fc01371b01937f21a1ffa02c9c599ddb61d3d6fad661d84e9386385ad","0xb18aadd40d6385cad7b2e4677fa4d3ff81e496e571e3cc9e12a89042fd76e115","0xb7fca2759de79571c473475630fc10ebfe42c70c6d1ad070fe56edf6988b12b2","0xffebbc7714d9eac601a0363052d59fdb610f12d30c00a66c7d52ee108b380945","0xd96d1420749b485413a966c86cc2423d6c685180e72ad896f6740609e50ef2eb","0x8ffa90dad17fd2c41ff4904fff4b2043e8c204dd21168c4bf04756e82140edff","0xcf77d659ac62fad6d638dd7d44de788c44419d3796ee88da1b61827a929737e1","0x5b4b861cc70b54de79366335d731de31a69a16c91be3fd7d3e8948fcbd15eadf","0x8af0fd04d8799b438d28af2b67bc07c41335b757a63ccbb7664509ddd9f1562e","0x30e2517334326440c424636f518bfaf73f69e52851a33d2776b7bd6028eb8e4b","0x55c51631bb8e17f6a4d7b41bbf9db2e7e8c77b79ba350fc400ab396e4e78f2d1","0x4fc097c6bf1286d112d36b13aeb421a87978f2a871087f47f20c37e714ea2885","0xce750d7fc692a4681f22288030ec40b5427193ac1b816e8af2e46e4126167ed8","0x22f35570f3b127971f23191aca3faafe7b247218bf49ca8c59706a8e9c9c7305","0x12c1a271acc9fb36c455e44571ca010aef9bfae0a5637b783350803f8ddcf80e","0x96f70a4377bbe457715bc102ec0d676cf0a83485cc62c3e9bc6cee793228f052","0x016e5e2103d7dec166cf0dcb3a3e5f815e2be69cb45acd056a1c2acf2b5a03ae","0x7a71ebaec48e2e65082c242da4750a963ac81ba618f0c192e973761a64f09f66","0x8f0b8ea25c1220e9126c3477607937de8ea7383cdb6afc1753e0df607c8ed8e3","0x4813a64f3872ba1952c6cf90288b27ae3d6d67eb13870eb9ceb2171584641ac7","0x405d3921180489fb981422d81116741e360479d4c67b9683aa1a08dc96a5b9b2","0xadbf1507cba869109a8e3a16a3cd39776ee4f21ac52b1ca2a0fe7ca2311a8911","0x1e01e0296513cfed8040dbc9bca26edada1065299dd080316ec1ee0eae19006d","0x6520876f392516b966851ebd3dee2a454da24d0900d191970d906a6dad7e93e3","0x669d506244f143e5e4739101e18705340749b3a92935f95bfd73dfce4bc9c8df","0xe9615b5d441a8c57db93fefd1204d1d368d206284b3a900c1fad62a82920edd6","0x78c4b8c32efd5f3c6547f932e0e85492ed5efbdcafe4b84c20457bdf6931a579","0x3617af71c66f4394ddaeac7416e48b84cbc0f0a839c1e6d7c422590e860ca9cd","0x1aee1cddcdc8dd49731cc2e6ef86063ff4fac9d692656e7c374900767a305d6c","0x7383dc4e171d1e36716af774f627f482be4e9929c8e6c6731402da0fb291c034","0x1656e294eef8b83937bda72c86b8af9b6211cd1132a409b0706998bacf10e182","0x40a6dcb604211f6c88f85e85c1c3089fd5aec3da66af63f5ff0365b97198f86b","0x1328d611d243e13800fc4420976d7b0a28cd4899bca11d48394c7e932c84498e","0x78b47ec8f03e09753f2c23d627093e285ddf9e8e22e4cfa44b8cfddc9c9145e0","0x8500b05b1c8c758abdd261ab4a1c83885392bba558884d65f3cf4d7dc52b70a3","0x3b55d74ae0c2ee22b4f47792bc231917204d49d8e53eb02fdffa783b77cf8475","0x9d081f0a6212dfdfa7d28f36a04894ea53a777f7086eb9001efa7d79a65c74f1","0x7ac084eb58e08e38c4d2aa01a338864b994e650431a326957c12a3f5023a4ee3","0x5e15a324f4605aff5f78835bdec89570d76762d559de1ee57ee084e148a8b328","0x6d52d78a633d387bb2289a11c8a07d49471c1414d9556b164083b248419eb5f5","0xb4892ebd00756b6be7ef887fc4174b3be0fd8db29dd0893d03a54e398067775a","0xaa1deb14698df8317c5133d668bd7a1496c50af3625bd642f0107d7c41e3deb0","0x4c900cea8c7c95d1a8f86a44421246c8fe96ace9b174bdcb54d7acd402c4ede2","0x71c6effbe429ef4863a25287099c2cdb8776b1c03534c4664fa5ad8809319f0b","0xf71bb8c054bf2c9f6b05c04785a85fd021d4425dc939b1cda76eacfd152c076c","0x2af3a7401ecc3d088ddee0f5f68bb4fb72958b66b1fce7fc03f885809de34224","0x9f3967efe5301057a303b9d088fd48ab9dc9e278ade04f92940918942cac9058","0x6f355af61a2fd0c22c512478d3919272717b4431c75f2084a5a2b7e8b9d47412","0x7fe1017c86556f3db357c27db88e92510389f5c0946c1cc771f61c65160476e3","0xfce5f2aba2073b4dc6f6929d6ec4390a891d383810523e9eb2796aafdb9466f6","0xd5909f7b41bc3a5b7a7e1d59088cd11c585d801f735ea03553850c2f2668a38f","0x9e65a654a4f15272a342b3730888130076fe53d2b9cd50cb807790abaa849706","0x7f1116febd43893525d9b73a4c821192f6b90d5dbded75e5cbd4cfc462d074ba","0x0fd878c87342b2778ab3ca56e2bc6ee7da15e028b6a8cd3b3d0edfbf68f7ecdd","0x48eb84632adafc36ade5f4497e16db58cc07366ee5e855803a6043c10829f1f7","0x1f34add5b3005927c7be79b08d87e243862352991b5ffddec20f044bec27fec9","0x041a25297b9cc993f6ab06b229697ed9dabe30fb31adb8b7ab842605a462bf7f","0xd47c8674d46db513ba828ebd43eeca67ec68d822cd6d97e06ccc7889b4d1f0e9","0x464458396634d3c39f6b48da7eca8d5eec03065d9f3a3343eac5cb6b1a89176e","0x89ee2c7c52bfaa9b861cd1b3a2802dd66b0b578b269d68f010603a55babe6c4f","0x76d7ee8fa047b39ba9e513515915e92fb4473d09f5bd138fc2148f6a9593b495","0xd6ff8564531530c811345a1ae0ee6fa285e89b7fc301bcfa3fcf3f67a4dfe7be","0xd331f4318c8a3944226976a5b5c2c4ff7769dd05bf442e321df601be32401db3","0x16646dc4a3941cd099553f8a875af9a545bbd20ccbf33cbf1fa91b1b8da96724","0xe92d42a8b035476606677df876167ab28cb28f3e43cf5e2596b12bfbad70761d","0xa9c02c3187c66d785fb05eba9a87bc06766088596b2a48a669f07ee2f293e705","0x2239d461a356b9813ed7fe5c8816de9758dc3e8eb4a8125956f5b622d2db4dfe","0xb44d66658e6cea7c4462f04e60873cd93932b1eba5d2754814589eb55bd91065","0x9d3d93d54660163e1a2ea54fd5f4318fbca0e44d399cb1cc10381e02ec0e1133","0xd600a3902e864ec5002cf321dc87071b59de4cf5f440a64e7110449b43818445","0xfacdc420d5694ba60389961af6cd62ec0649fb91aad2ded908dc1b239055e8fa","0xf14bde434f78f7c4bf3421cbbcbfcd3ac8803794737310451a6cd45b8449c98b","0x56c2e0f7cfdd41319cc844307e74cf2880a4dd3b8a21d63bdbce57c62457d7a4","0xbe662e01df6f6a5d784483e5ab3f25837b79dec311ee8f1f41d76723e774b756","0xabaf9cf9402d9572fbcab160df9f4be8555c4eb71075bb4f5124cd6394bc8eb8","0xe3a414622d90ef9f7d5ba092d7410645f0f625afc3ea10a60d693b0a8ec6c039","0x1bf4854e5a420870dbf5f4f55f255b3d657143e5ca62f05ab9fe94d5ec18406e","0x8e5b200369ba196eb48e646bb94eb0d75cc4125bbbd8764861cc100e7068cf6a","0xd7b72c2ad8fb5381612d921b38af4c73b614811435ca2ab0430b5e8cbe14b45a","0x4f6c2ee4352f4306526e42caf728342b91f10c1d95fb7c4cb29e727d44a67422","0x9fcfc83f5cc423c236bf2ba5d871f1e1442bb01ac683254b7c15704689894a53","0x799952ef892b23128f71569f9b80970470377e93627ef88888e0a67065b5afa2","0xe4128e9c11495e7c6a8c371fffe9d01b3e159caf3dea5c71f1ca3ce6b5e18fed","0x76027cc5b54b8cc5cd30d863839359209c069222b20cf57894c9909ebb1b4bea","0x711ff2f604aba7686391a2abfe5c3c8d35950d05934cb8dbb9e47dc2d0135b94","0x726959e8e07b3808911becd8d0c17d45ae5a5f45b36c8100e927a5a6dd5fdbfe","0xfc0af1ae4a03accb452ec88967de5845fca00e28b21d2f23cf4e99bb01a2cad1","0x07286e57ad99709ffd946ba35a19c4bbbf20d12c0b030ead926381e73e01f0e5","0xb51ff90065c7b245246a4c1cc0a1f66c49c6c72b1d37c56844f7b22ad840cfeb","0x6fb862ba12d80f0d45aebe1a22bfdcf92a182552c4ec412ce088ec3f2c8e755f","0x02a6920664c9f8828d23c17ede9b20f142949613aaeded0ac5e14f0229fb9eff","0x2dab9cce0326bb313d1b43f69902ca7e8a2885cb19e00ed112285be436b8dff3","0xf1ea7f2fb51e426c6e844534b9a61f4ceefa1c6e907a0956b69c5fadd29fefa6","0xd2e634fe2fb21e917e021b84634762d77ee91e1082bfc1a6fa3ac893e7750548","0xaf453232bfe4590f18e73cd8a683130a7fe2949461116714727888573a201f5e","0x33c9b30d68f3ff547803af3304b2b6c5e55ce1b17c7f5cd1242e69457198ed67","0x60fae2540944f5f5f2bce8d5c7ec2b2304f500a3efd2266647f17e07f4dcdfb7","0xdb48b1ab23cc24edf2e785f44045cfe74ab1e620ee517181985e7df0b0cf4437","0x8974ba3fc0a73a83995ab6d89c503551aa6db4a484dc3f33b4440814a8437303","0xbf2a78669a64db50bc28c4eff133f1db8f39b2323da6a131f2f60f11b327a1fa","0x9254dfec0cb28f103bfd4e25a2e3a06d10c36a64b153176234be1c48a0566455","0x9d3cc06c3937557f1862da9bdb299ebf9ee986a51c41dcd1f2e91077652ced8d","0x8c0286446c1369243d80955c97cef98aa0fd7b09778754a868f9cdd69354c8e8","0xbce07e6be2cee6635686b593b675c4084905e94da4cbafa80751a2ba9e5b5298","0x3d4f7a685caa6c40eabd5de4c69fac73152a08a2ae7e72b307d4da0cf4ade826","0xa76719a78e8e579e559487f33b9d9fc6065040d3931f2a0b3c9f2dade92b726a","0xd17de09787ddbfef94b572eb75ef1ae424718b172c1338fd7cfdd3a051cc3d6b","0x185579849c0e9aa1a606a1850fd5def91a1db337599665c55e5566999ae1e55c","0x63839bb45cac37adfc9b11e8de508fa61a384b43a0ad0eb2850c2f887a7f8c32","0x6702af2278fbd02cf8e68636966ec6c267f7aa6c53a7000bd79b2da5b4ac560c","0x1eab76961ff3de036a7bf2adfce9fb3b5739deb1cec6cac23abb34fdde9d7e6e","0xa39702e7d3c454477a7cb9e2615bf0865ebf55fbad0f6c8aa7f9d8971aa19ea4","0xed85da690220ab91baf719d3439d22171c8f321dc59b8ad6fe0db6e4b2dc2458","0x98d661b2acb7f313dce9eec7e3c48f5b1916349c67514795a207e856eb9e4b18","0x5794e67ce85b69607ffb433aa456361e14c0afba4f8ec092d9ce9831b5ee6d09","0xe7a7a75729f5da0367d1c79bebef6fc74aa8886fc4452b74db9dea8e9bc30dac","0xfddebfc8cb89be4e3f512b58a6876b083ccdea67f3046575a5689ac831865b0a","0x5773f1767a1e784ff5044371688f4c1949b5e6b52a4726cb9df835e0406eeb77","0x0f3a4cf051991138b63fdbea1ec8b3780bd947713a74c3bd628e5dd80f5a3541","0x6a6025260656819583468d3f730b6bb5528d20f4b8c80927fd3420fb8fbf0238","0x2f58136498d025f0bb30c8c55cf3781b3b1f8fe5e4080e14ede510c2cbe62c64","0x87c0a3fb37c01c1b4fb127e383576b4d68a2783b89335e0ad0e10a13e48f98eb","0x98125dbcec412b79c6921cd0c39e05dea43413d4cec210edb47ff1c9ea9401f2","0xd7ad404e65f321493ca93f6f0d2853a1660e95f9de50797d7808a9bb9e00e21c","0xcf96afb107414e1b0b383dff311ba84820960eed6130c0a2200662580dd5a23c","0x5f9bcc1536467d55d5531548038654d7c2b8579e8c943199e3eddd25f1d20bc2","0x39811f217af638d169d234cc885e2bf7edfb760f307249d9403744eb4c5831e5","0x5276c6262673d42e9cfe03b3cb3dab63d2ce8ae1766450d605b27b52cd65151e","0x871369e3251a8674011081fd9f755c5cfff728306969dfdb6ec13b8187978f97","0x393af11b8d59b268f62794a960f4e239b4a7951e48c48b35126853274b4c1a46","0x98236a771602526744244af20d314450b28af4daf2a8c3b03f1b03f0f63b8abf","0xc90e59530b4e7dfebc8f4a42c21d7e152d02fd9a65744b40d2853cb13e9abe23","0x2ac5c70b5ec5dbba4c7c901588abecf1e95458a79cecf4be62cc36633416e587","0x70b0f21db96de2bd91e39457039f4f559443b065668bc6f74796933e5b4cc30c","0x209a76661edfbeb765c0b7e35c7f6666824a109fa33f67161f9a98f0e87272b2","0xf319ebc84419b000d681e28a5c7f012a1c2ee5d8d30ff45d75ff84218e3ed9e2","0x5c7bf3c7f584ffa5d2cca52845c4e5483b20658bcc0d6b1b521cbdec991997e9","0x361b39f1fdf3f9182c4a18dda7fcb1ea0a4cce58fb0a8660477135b349f3d0d7","0xac9ea903beee814ea08674cfdbf38c75bc37fab7337a038c8074910cf8a94cdd","0x7552c996caf8c85dad7965d2e18af8bca864d1da825beedded82598e83764015","0x0d61ff46ca7b4f9906e9cbe2f243f90104a59b02c3cd65952bd4304f7818e583","0x4f1206e739bd6d05c59ce4b737190f6662c340aec4c09b044eb0bd88cb9e1b51","0x272f26686029a4c62ea77e26368cfd4fe4d577b5d1f1fd5dbc28658f001976a9","0x1843aa9a44d2c10bbc3ecfa1b7bdcd64bb129ff0156cc0e43ee2c12cdc6e17fa","0xe8eee24a23fe65ee522a438b413c7b232f00c9791a028e41c9e69032996e2b6d","0x3b1fb9eee4fc1e14f77d603b7a8e59fb2d897ad5f3b8dc00dbc16efd19134dfc","0x38e82ef20f33aae1cd4194d5f81d5dbb57da1e854b09f3e176ae4c18411a0b5d","0x27f5feebfd05597181c1dd7aa9d7db3ff9a05abc730f823cb4f7ff987241ce37","0x68ed81267e5d0bc1b6f21f0fddf41d9d1aa20af4459efe88422388d4d240ec5c","0x7330664cfb4298a67daadd625bc00cb986ad7176e71018d47fea02f2dd0b5e8c","0x3dc320bb0598d11ba1aeffab63a8ffd5c440dda87a3e8e97d8a108140e5769c1","0x5ddf110acc7e89012cb4755ecd713c08ef3dd6dd3ac3b18e545025e08e5b403a","0x1f1a74fa2d109221046381e90badc1362d2eb03c56f60e91e9ce56e5cd22880b","0x1f8e8aed671881629b96538129e342ec5b4ac2c7b34f3da7865bcbc15aa81a08","0x73cd6f3588ba69e9231204102353accf5bc5db61688a14fc243ec3e5202ce0cf","0x281ff56f2a28b5e700239cff48d55a813c0edc3e7b0eaa4a89e8f4970ee507dc","0x290027b3e107f5254fc24647d6ef4199794c3ee20649fd07b57cf1218a57fc79","0xb793e0cdb4a3577615c2e4593b657f4efe6a6b5ab8d204c89aabca1333568876","0x06c40de1fef805eacf69b7b754ec29cdd2fa1eb4b386c8e17aa61bf39ccb6b44","0xd314921c6ec1abd55a67b908be5a11054ef02d034a681b6903643523e915a14b","0x7e50f188e35298b7f0354214ac81b4e90c9cdbac084771d347d7509c1c64d790","0x731319bfe45085a828ef6b2b90ec630d4811dc77506c49a565c099bd9879f8e7","0xe692ea7f70973c8b07c366cf9bb41d178c0fdb835f03c0a547b56a08283730df","0xa844da8d5cc5ea85c23bcf734a108aa45a26f4fa6e8f62a57fbd5d4a57d16f8d","0x060591ed329c24701a72ee30ecd5a0b940963cb5ead67419ba96d6efca477cf1","0xc02e1c0f93d2eca21ebae97e46f09358cb182084c89e42a40976c760aca9d5c0","0x87ce974858174b6eb36bc2d759a16ecc5cdbc04d06e0b194c987d3f409be3498","0x80b5258fe8b6f17a1ba06f321830e6ca39fd24fdebb2f9fbae80238907fbfae4","0xad871e5e3b636595212e33a2d362c0a80527b2f42edbd413b3089535d03a6214","0x07ca82a3b8fdc99d3d90b9da307b75681f5e2e7b959237d34f9bfa99a9136dc5","0x2dfcf0b047d7efbd7605fddd346ec7134307bedd1ae3c3972d26b11129c7ae7e","0x9dacb062326e039741611899cf1007dcc7070942dae2e149dcf5009bba4274a8","0x7df955bb17e1c940ff70a749a359d3b7a4928c7c73f27897c09b007b219acc75","0x68c941f5e25fc9e1ed831911a363e1be490b55d1a95df9e3089f154f4a1294b0","0xad4310a56f5eb205e35f486077709fd0d272a901aef6e422445c4eb75631c967","0xd55321343fd11311c83b850a104e01e58f954c7d40c40e8901718aee2ff79c88","0xc09df8206a9903aaf05f4284f94645a1a868429d7e2f33159c5ec78982dc3adc","0xf3761e48323dd0008ecbfb9ad25b6a483e027fd4326c4ee7f91426c06fa76fc7","0x1a4efeb2d2cd49a02dbd3219c862c23cf200a1d954e853020866de8d1a0f2226","0x39686218060f674bb41e2da125e6672a751e1d3408586d87cc468e8dbdee3ee8","0x1ccbe1dfb4fd31d3ddb29cac21b81a682e1204f1be9a3f83e59b6e91960d1515","0x8ff1b00625c92c8cebd4e1c2d6beb177586ffa2b83e139539ac2a628b8a2a6c9","0x151b8a2b1e6ebdbbf487cbccffed1785cbae79b7a0542cb18d9ec1e3b6ed08e6","0x51f64b838e49c727412ec5c6244098645fbb56496ec70d8a09e92471dfadb4c1","0x00fbbc00a4ef17152a89e2b643bbfe0cf53622de971d0d02b49fbc8a67e9f24a","0xa0b4105eb08064ec73c13dfa3b952768bbc089d04ac8b15a9a5fa2ee28c0024e"],"transactionsRoot":"0x62e37a3921b729a7fc5e8be3fa685cb9dd88032a370fed049b8543f264a9eb52","uncles":[]},"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","block":9937218,"r":"0x12309ced6626c28ef82b6e086fae69233f11a59988b6381484ae4217f16ab556","s":"0x64ccfd04e01e3446112857737c2964c973654eebd9f66f5dd7b92863594e3fd5","v":27,"msgHash":"0x684999d8bb002f0547d945c96127656b9a1a9ad9ae843216ceb67c87604749f3"},{"blockHash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","block":9937218,"r":"0xf921ed047e75ab56b94fb44da0ca286cdb9991000ef274ace5dafe1a096eba5e","s":"0x11af667e6e43acf8aa80643d482e8fe91964ca7949dd6fe86f6a6fde0b363561","v":27,"msgHash":"0x684999d8bb002f0547d945c96127656b9a1a9ad9ae843216ceb67c87604749f3"}],"transactions":["0xf8ad830ac2cd850bdfd63e00830222e094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000075c2f1abc8883259b328d4f55bdef1dedde0bc170000000000000000000000000000000000000000000000000000000007fcad8026a01230f508c74dd0f6779cc8ee8dd17e3c4b317c975645311860df13eb7c40857ba0229ba3b4d88812a99b272e59283ec53923ffe01082481140e8b23405f36ab801","0xf86e821e58850bdfd63e0083015f9094abf9858fa187e37597165e1476e267be3c09f7c187e6ed27d66680008025a0fa4876c4bb5fa73150433b3a8e9198e4ec177db8497e927320747964cd7547b3a006ee804b91eaec495ed4f75f44f3451b67cc09669e9f396d04c2372f3d8f4cad","0xf8ac8308fc6c8507ea8ed40082fde89468e54af74b22acaccffa04ccaad13be16ed14eac80b844a9059cbb0000000000000000000000009f713d7f8a0c6f1a3b0bb8ead092d5c0c4527fdb00000000000000000000000000000000000000000000000000000007558bdb001ca07ea59a3a0a1e8388bf868bd02b7c0cda599e9ae6d78a8c3f1dfa93e3af7473b8a00b45ffb1b4f6c2bfed8249a8810eb9640af878c77eb8fcd1f82fbc56d4af8e95","0xf8ac8308fc6d8507ea8ed40082fde89468e54af74b22acaccffa04ccaad13be16ed14eac80b844a9059cbb000000000000000000000000d2a9f1132d24c3f0d806e6b1226bd19d34f87f18000000000000000000000000000000000000000000000000000000048a4a63001ba0b49b5847ca99a31527dcfc6fcb8a3f16665eae1f0cf9889f04aa927fe02b4234a0558ffc47fb951f92fc4b13528a886e562a8bb7a8a36bf41578a3f25cffc70fa5","0xf8ad833fa54e8507ea8ed40083032918940000000000085d4780b73119b644ae5ecd22b37680b844a9059cbb000000000000000000000000ac2fd5f56b86b0a12fcdecff9290be05ddab13e3000000000000000000000000000000000000000000000001a83e75087fb1000025a007aba932e0bfa3d539c75e988abe7ae476db32e9b9a90c155013b60b04c31f46a03aa4723d52519866cc79760c58c566842f7093ed916f083bcf2d388c7607331d","0xf8ad833fa54f8507ea8ed4008303291894a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb000000000000000000000000172e5d791e919419eb7c0c56d941730cdeb082ce000000000000000000000000000000000000000000000000000000002459aa4425a0ab6345220662ecf1a4d763586d21579925f9dfb5ac9286d72238a5092026ad7ea02f97866c9ae4de9733575fb63bdb1e4255464ec6856833cd34c4fa46e341b969","0xf8ad833fa5508507ea8ed4008303291894514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000251e93d51c5f2a1e60b7bc90bc8b2534b68e8f4000000000000000000000000000000000000000000000002b24b50e12e67e700025a0820374338beb3d537c09ab769097df76982cc10483318013bd3097a99062570fa07a75e917484950145e4dd54f26508debd9969c404937a54089771a8b3ecf6ed6","0xf8ad833fa5518507ea8ed40083032918943597bfd533a99c9aa083587b074434e61eb0a25880b844a9059cbb000000000000000000000000f2fb5a2a92b263fda28079f8318dc1768990b9fb0000000000000000000000000000000000000000000000000000239f235bf00025a040c609ca8a16a90850fcbe81f3f2f49c0608ee5bb58342391179c8e46e07794ba03c0d693d1fdf675adf6bf9ecbeac97f081217937e9e8911d05b3b87052a7055c","0xf870833fa5528507ea8ed400825208943e989027c6034171fdb912d81b70fcc46eb6d1e089042abe713dbdf380008026a0d5dde1918f6aa023ddb42d454786d027ad7eaf4d8877d92e4d1c2cde55dad969a002c276996f7d3da378b42a9cda02dbb04f90b16bc9f3bfe9e444a04fdc024777","0xf86f833fa5538507ea8ed400825208941bd4aea585ca71c00c5a694ab8a71e968dd7ed39880c934e1480ded0008025a010ae482060d67954f7bdb3fd95586ffd6bf440646ac0833c071f7cbbb47a4329a0344769fa8e21855323cd1f02d1dc456a6317e150f24384960b8a2b68ca6325a5","0xf8ad833fa5548507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000053b7de95320b8474e4a96302a8d70567870892500000000000000000000000000000000000000000000000000000000287ba543026a0afe104465085d312103810bb6fb2e89666184e136f95005ec97ac83d90152077a02f6d08f729e7adcd4e2240a29bb995a7238e62e35bb8f3f7c3984e01808da5de","0xf86f833fa5558507ea8ed4008252089401190eb8ff6507f85dd27c2726d59a617ac0a81a8804fefa17b72400008026a099064bcc0ee6732f8aa44ed4666d84ede1b27fe7b573c6a0ae6288e023cfc835a0269d9d191054698f1528aaf3eb2066ef63e87ebc1afec66b046735382b249d37","0xf8ad833fa5568507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000f578cca76375a83c7bf70d536f859adeccc50538000000000000000000000000000000000000000000000000000000001dbf343026a08fc5d98f7dd7a6ba256ea2350f8dafe4793e943dc6e3d06d5307c56a76796a5aa00a55b52a421fc140710417473cd47955a4d093a6167e688a1c4deccc091aec3b","0xf86f833fa5578507ea8ed40082520894f7757e7783eab1a5d26a4522f2dc0ec7579b57708803bf3b91c95b00008026a087fbb7a6d31144b863e79f0fca070d61fd355bd00b42cb7852c9019539a3fd9ca038b761f4d50f4bbed4f0dc2e72299053f23a203de26808704037e335c1203fdc","0xf8ad833fa5588507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000015b9d1f20a3a57ec9d3f55ceaf5cc66f417fa34100000000000000000000000000000000000000000000000000000000059889e125a0559456cb166cd667f479c1d0d4f10f9c5c0ba209f21cb2786b3d5746ce8d4463a05464cb35fa51cbf3d249b1f19a3779072ba22f5b926f2a13e85810e05cc7123d","0xf870833fa5598507ea8ed4008252089488b6cace7c485db4a33f4da78d10abce5820467f8907c341f0cf4d9c80008025a09b07a68a5f1d464935c9c7333c7955912f8bcaad1fe31b40411492f34eaa89e8a070af6a01b18ae4ebd59b4b4e84179c091fc008468d6f6e768f3b9c54600afe25","0xf86f833fa55a8507ea8ed4008252089400003605d910ecb5e30ec854b1e366562b1a12808886e266f566ff9c008026a0dc66234db06f40f9f7aae6608a60178182d07404913d8d3533396f5c7b2caeb3a044a8abc35cb47852ba5dcf2b9fe45ecec9cfd20e4ecbc49f450daf7a5857b283","0xf86c81988506fc23ac0082520894b0ebe65d836a6591aaecaa7471fcccef68f8c59b870e35fa931a00008026a07efae8330e4f6e1641e5d548bc6758e6d349d7ccfea24f57b682084daa9224a7a0665a84915dd4538dd95e0ca07d6a194d8037d687da2c67f24ef065657ada8b42","0xf8ad830c2dd58506fc23ac008301388094d7cc16500d0b0ac3d0ba156a584865a43b0b005080b844a9059cbb00000000000000000000000071254339e7e73c5ff115c328bcc54fe44b5f12310000000000000000000000000000000000000000000000000000000247f25b4026a0e3b54e33a5e739941551a217caa4b891ff54ec0a8eb2e37a596d5c07f069cb23a03abab2a09b32103cd70aca3cfe7cb723aadd71418893216cdf31782adf6f3e6c","0xf86f8221ff85051f4d5c00830186a0942c5ccf1ac4407e2e0e792f71f84f65d4679af2bc8843f8e8abf43b68008026a079b1336fd77e23cdaa1504e1e460714fdec5b3475c1895f57be92be06433316ea031f3cf4a2cfef3fa42a681a563cb4605daed8e4e961999318ff58c012e3cb2bf","0xf8ad83880a4e85051f4d5c00830249f094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000c82a47850f144aad67a29eec2dcaef5b9ab54010000000000000000000000000000000000000000000000000000000002c14fe7c25a00f2982fcdc28216d287b29a934b01f5b7c8e9713020d7779cebc8b07a02a2876a05bfa3d719eb0454164e2587391da61e864a00e3d950033040f1d6f5ef536bea8","0xf86f83880a4f85051f4d5c00830249f094c8817abfefb074732bfa62af629e2ef2c701532187e7a7fe3c939c008026a097d924db9cc558b6aa9927eab013309be3003bb3bfaac1d1fde1fa4e21e509f6a015515ed84fd52b8635da97c9d9d5727a7beda7a5c544934a42a19a32b86cb6dc","0xf881808504a817c8008307a12094a22c1b5320108c19db53f58241fd64b10556229688011c37937e08000094bfa6883b31dba961c0db9fcadd45f2ad651b64c926a02aabee2de83b5f8183f0c32d9fecf55a4c09c796c6f9618b2dd2c7989048e185a077dd136fe2a5d79855008457e662ace43d05857628baf134c3a47c0b954cd189","0xf86f820f4b8504a817c80083011170946d8e7336a9d21a5341d0d56283c7db067e77505888016345785d8a0000801ca0f7b1e0ca0cb6d5d7d1dd32131cdd9174d3683265f2bc38883928d04dda429846a05d298828d3eca8db494bd13e2118b64537daf8404ada1434a9ba23904c9828b8","0xf87183069aea85037e11d60083015f90947930f4e4a31af453ec937f37f153420374325ccb89010e96cfb1f69100008025a0d71300f6491410ffdd586300430d89ff7a506efa2bd678ccccfc8109c9acabfba04d72aca1b1a1b539686ee5d565b3c128ae558f82096337001301672ade0be42a","0xf86f8305a0458502cb4178008301d4c0945837ba345a5dfe649644c6a182ab0638355b280c8705543df729c0008026a09e9f073c4a174a128b9cc3557ccdf6f636976c3ac3be157bc0c26847defa8283a04ee8dc7cd157a1ad9edc98df533b40202283cdba22aecf5534e0f91275f8bae1","0xf86f8305a0468502cb4178008301d4c094babe4b38aa7a75197c81fdda9764dac16e437c108705543df729c0008025a02e76dc375ab7c1cce96f81133f5554b29454a300a137ac4ea27f3f85c3a4c003a0114e7cf8598c56a0ed20726e58021e433fdf60fa4c02076abfa4b84b0b1681c0","0xf8ab8275a58502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000df68356feacd6f58977c024befdc6195529fe51d0000000000000000000000000000000000000000000000000000006b679f65001ba0c104c411f44083472d27f7261ff377155179f69d92f2b7fb2574d857d4c368f0a07e069057cb7d91654050fe2ad88cc766f6fc90f06e236336a9b950171bf4d889","0xf8aa8275a68502cb41780082932494e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000e45f62b381e003090d09aea6304cd47e89c265540000000000000000000000000000000000000000000000000000001592a797501ba0f2d02788455eadef53902b2634789e88b22ab8efecd82098eb0e59e55259086b9fdae707d2a573de8657df87c9c75fb05ddc67bd9d7af49ab5200fd0f2a46a48","0xf8ab8275a78502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb00000000000000000000000086f7e6342f54643e09d3373f04b59e798ade70a20000000000000000000000000000000000000000000000000000000be5cc1f001ba0fe971df6fb442a89936d5a691e9228c6aaca1c00be2a1d12163040b12e325ffca04e50ed690c10a9511c72f1110d9177fa992368070db71b8909d885c62f7df2e1","0xf8ab8275a88502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000c139ba9d0f27a7e34ecd400c835da1d7b2cc9764000000000000000000000000000000000000000000000000000000239396f8001ca03b89f36d8d3be1b8e6a3eafbad2b0a0313c6b4995b9731169d1b814287042bb8a03e47406e40d9de6a0cb9399f69860636913f92a5e9fc29c9097007affc72f294","0xf8ab8275a98502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb00000000000000000000000098cc7030836dbcf1c5e2d18031ab3a157533bffb000000000000000000000000000000000000000000000000000000171ebdc1001ca0a13878b452c7acd8c46ecdc4feb775772931ce47e907b618cd6b989111dfb16fa0088b749ca3bc6851df557aabdaa72b0ede6de7d9b4ddf9ce2d5670ea17f5397b","0xf8ab8275aa8502cb41780082932494e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb0000000000000000000000005a42eb523ccd5ff58bfeb508373d6121ca59efd300000000000000000000000000000000000000000000000000000112cf5cbb001ba09290a91a776681c9fb9affbd1d81dd7261510fbdf0cf5ef43ad596df2414f76aa038fed5f344fc0100453aa8fa54de5e0b1a71b009bfa44509dc9c2f96dc9b37af","0xf9010c8209b68502cb4178008316e360940ba45a8b5d5575935b8158a88c631e9f9c95a2e580b8a468c180d50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000007289e00000000000000000000000000000000000000000000000000000000000000010022a7c1100000025000033293b3c63730000000000000000000000000000000026a042ce3e6c352c27f9c01f474f8b3a68ea99091f738e48d6611c83d756d6546a37a0461240c4579d7d6749b88a64469c9a47bb4f8d48b787bc9dcf561d8dff16c4da","0xf8aa078502cb4178008301d4c094cadb96858fe496bb6309622f9023ba2defb5d54080b844a9059cbb0000000000000000000000008f20a07e0541ca2db9152d7e521aee5d639b211d000000000000000000000000000000000000000000000055e638836db86e000026a049c347e192b26eff3340d30f1e1e164cc83d724fa6c5c162509a166e6594850fa05e201f893c7a59122de4b703237fdb40ff66ad332ab84fcba48d1e74351ea6c5","0xf86e824f3a8502cb417800829c4094e80a115935c523799403573b6d5d3e114d5e03798806a94d74f43000008026a0155bee3e281a31b628bfdd0014ea660808597525a0282eb93bfd98ceded648f0a0250e69fa0845c5c291f7e2a744fefa8ac71cd172d6b4652f22e9d4b680cb8ade","0xf88b8242ab8502c667c8e58302e6309461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adbfafbc1ba0adba4cca4e9555eb8bede3d0433866376a98b223ab42293704e9e4c7d1c9a86ba00413d0e145379dab950d903b84859ba08c9a0f5b6db2680f3d5c08c7b7a463ae","0xf88b8242ac8502c667c8e58302e6309461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adbf66981ba0db8189f3aaef78fc825564d356c3dcc69544e3f7cd3fdb2e2ce4ee2bb757819da036079d587b2a5907791cd6d037e2fa2587ded9895fbf115a0b23c1ecfbdd9690","0xf86e82fac28502b82e9a7c825208946f964a58a2788c886356edfd632c2ad15efa7e35880f97f8a06f6b80008026a056bedf4f0f3434cfa758710ea95e25414dcdf08ae500501a9482835d13356569a0470d22308bdd8bc7b8dc537e540f475bd411e20a8fdd82e11f869adbf56c47f6","0xf86c808502b82e9a7c82520894777f415324d56e1d54fa832902d8797db7a4c57c88016f09e36125205f8025a067dc2fd858af1cc14d3bf251b3f48b3954fa518757505414d85b60623c77f400a07ba62f446c5201670425c8fdb2f3d8333e79b2daee5a88f1cf021622bd5f45dc","0xf86e8202098502b82e9a7c82520894777f415324d56e1d54fa832902d8797db7a4c57c8802c616739871c2408025a066008d58bba146bec9a7220dd0029bd086bdc8d6104b9b309dd2c729d40fbc09a01f94bf14e189810c47e819fbd1528c1a5ec62c7ff2b2fcb8a2796d47a484e61a","0xf901e48302b39e8502b82e9a7c830334508080b9018e6060604052341561000f57600080fd5b6101708061001e6000396000f3006060604052600436106100405763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166390b98a118114610045575b600080fd5b341561005057600080fd5b61007473ffffffffffffffffffffffffffffffffffffffff60043516602435610086565b60405190815260200160405180910390f35b600073521db06bf657ed1d6c98553a70319a8ddbac75a38373ffffffffffffffffffffffffffffffffffffffff811663a9059cbb83866040517c010000000000000000000000000000000000000000000000000000000063ffffffff851602815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b151561012557600080fd5b6102c65a03f1151561013657600080fd5b5060019796505050505050505600a165627a7a723058203f339a2d354208169adb91e00c0cc7ffc9a9f9e67930818df75c3724b686179d002926a061fb04c6a6df308fd675a1a74a6ee56fe97506d62c7e33821351e0807a600deaa05d92c07c402da3537221fef687442efd1027537d072bdfaf1ab867756dee648a","0xf8ac821ef685028fa6ae0083013880946b175474e89094c44da98b954eedeac495271d0f80b844a9059cbb000000000000000000000000d35631b88c6cd88383376978394232287e49fc110000000000000000000000000000000000000000000000138400eca364a0000025a0109922604a131435cbde54ff3a9a83aa8a9286921c58fa725faa755d09eebb1ba03e5ee58fbf1d9e0a76f650533ff6c9e669bbe2c0eeeb62ae372a18fb6c5d2d65","0xf902f482011585028fa6ae008302874a94241e82c79452f51fbfc89fac6d912e021db1a3b7876a94d74f430000b902848059cf3b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000006a94d74f430000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b80eb3c2b935b7a9ef1cef38979c3e44a9537e0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b80eb3c2b935b7a9ef1cef38979c3e44a9537e00000000000000000000000000000000000000000000000000006a94d74f43000026a04d55d4dd9278ef9b6a6d7b128c98a1e57370f1f4a67a0b5327bc652af1486e43a06ea212505cbae75ab5c417c680539c061e7a5ffff564e365fa06be4b7e2b5277","0xf8908085027ef638008303ecf194bcf935d206ca32929e1b887a07ed240f0d8ccd22876a94d74f430000a48853b53e000000000000000000000000000000000000000000000000000000000004a6db25a003ad72dc4435f2064ca3dcf6f45d504724796712e8776a5405827d93ffa6efb4a0256f09c0e6f30ac339813708a3870018b9a8b5ba5522389e3d6f563417c8bf9b","0xf8908085025a01c5008304252b94bcf935d206ca32929e1b887a07ed240f0d8ccd22876a94d74f430000a48853b53e00000000000000000000000000000000000000000000000000000000000481d526a059b23366736c70b076df6f9de10446824b8d9a5655c38625adfe0ba9f8c6ee86a017a610affdafa5908ac78fc430d0a53c5a25c368da69a349f061bf3cbfd49496","0xf870830103718502540be40083186a0094b80db769e504c71c5f327a508dbae4cac4610bef8828a417aaad2f43608025a04876a92b712091896596834d096796ff64b4c7fb54f36ac8674d3ea896d0c615a07a76509c1998e9d94ecb308c8b1f807914f7d3d3b9404a747b48f7ef64bce12f","0xf879808502540be4008301c90894a22c1b5320108c19db53f58241fd64b105562296809404c501c8a50b42f15d820994f472121b84b7db6725a0e306902746f2d1d353249be9b97fb054c80b52f1b4454b1a30af218ec4843485a01be8c134098de25d174abeaef7763ba757f92c635b5024c71e3251f89cdae59a","0xf8cd8301e1458502540be40083014c0894bb97e381f1d1e94ffa2a5844f6875e614698100980b86423b872dd000000000000000000000000f19df15dac2eb9f5c3bdddb76e8d562574e8f69e0000000000000000000000008cdfa93c08a5db9f62231b0310100dbddc73fe7500000000000000000000000000000000000000000000060ac8b93fff8981000026a06071087b45c8afed41ec3e87d4c893b61aa250d0fa982cc519c2ff6fc93562f3a00410d8a86002eb4fde74ccd4e04e15345a41c3ac7f651f2608703cfe4dadb479","0xf8b1108502540be40082deb9947bc6fd7c839c7f726c937b5bd185f19af8988e59881158e460913d0000b844f39b5b9b00000000000000000000000000000000000000000000000000000002a5c6adc6000000000000000000000000000000000000000000000000000000005ea3471e25a0242e34d752a694e6f27a56dd9fa96c370068b29d22a3bbde8a52495e24ad14f4a05021986e41c1101743abdb6141aa5ed722ef51e9014680855c3e193e9783bcb4","0xf8aa068502540be4008303d09094763fa6806e1acf68130d2d0f0df754c93cc546b280b844095ea7b30000000000000000000000002a0c0dbecc7e4d658f48e01e3fa353f44050c2080000000000000000000000000000000000000000000000878678326eac90000026a068ac5fe381fcb553f726613558b476a0867e8ca42de34a5cfee41b695675fc4fa005d662ec8314a69164bb5c70e3c6de812e9b7b93d9406846602c89fab974286a","0xf8aa078502540be4008303d090942a0c0dbecc7e4d658f48e01e3fa353f44050c20880b844338b5dea000000000000000000000000763fa6806e1acf68130d2d0f0df754c93cc546b20000000000000000000000000000000000000000000000878678326eac90000026a0df859b0dec23e71adf720e69bf35175b4fed198e96a2e143127caae6286da843a05db7e93b9b285920efd90017c8ea9b6cb852de37d8a8e920da305e65cc6552e3","0xf8cc824e668502540be40083022e9b947203841a3d0f4e9ce2ed0a043c3b03a7ec97276780b864f45346dc0000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef00000000000000000000000000000000000000000000008b58b231df925f0ac00000000000000000000000005842cb65a699b0ebcdf295fd41e87fb4026b63a825a019d4e0a4f44be1208309598d5630cb603590aa23cf3cd350709c7c3662b642bea0119689a0b277b62ed9b237abb43e81b27fa1b9607cb50183041e10bcdf50a1ec","0xf8ac8232d38502540be4008301388094504b60a4133699c7056b58d3fe11ea73865a2d6580b844a9059cbb000000000000000000000000ba360e709858cc6a000f55c11f1c3450c7539c400000000000000000000000000000000000000000000000000000008752be58a926a0ea02f18d30c97e88a503082e9be1805d206ec720687edbdd3b61097f7930b252a0515d99e0889a524b7ee62df86d6c94fc6b85acc92f17dbd1e7f5133d77c9a657","0xf8ab8201738502540be40082db9194dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000a9b1c1b6829c2150b4be3105ecb302fa357da2c50000000000000000000000000000000000000000000000000000000005defda026a004bd1f743067a7faa21d24b9618920667801a792cc13cf4aa43e18266de90010a059acc26a65395337391a040e704ca53fd24866548bc68682f18fb9aceaa84247","0xf8ad830133f28502540be4008301d4c094966daed1348fbd894bb6c404d9cddf78a993291380b844a9059cbb0000000000000000000000006975759cc901bc0f6582e2c75368501052948e2f0000000000000000000000000000000000000000000000000000000131c596801ba00220070294c79316c34c427936352c04befb4f07076ac01f0db15d46b27e1cdba05cf3974fed2aec3f1855c4a5bc224f34659cbc936108dc385ca34bdf9ce15d61","0xf8ac824b738502540be400830186a094a5c43fff568fc2115d54499d4cf202bb490ef15280b844a9059cbb0000000000000000000000004e5c838a5958e74cd30b23bd33437b3abe10f9f900000000000000000000000000000000000000000000000000000001296d5b8025a051ff4817793c33255f318d3c76d8e4aac47748de0ba414af26693f39f4b7cb3ea01ff44010406119c88b1f2ee6bc126b390ceb16712682b8f5839c12221c9f0314","0xf8ac824b748502540be400830186a094a5c43fff568fc2115d54499d4cf202bb490ef15280b844a9059cbb000000000000000000000000f80bd892164cf32b315088d14ea09bf0f6c5816600000000000000000000000000000000000000000000000000000001296d5b8025a0b3268bbb02ef0b93e1d09f47425ccbcff0b5df8627f31c0526505d6bf9f439eda0570fdd1fbdad146a1901af20b023f579f28b10fe7e5244cbe0eeff033b890e85","0xf8ad83013dce8502540be4008301388094504b60a4133699c7056b58d3fe11ea73865a2d6580b844a9059cbb0000000000000000000000000b36c927d8868ce6ac4e367bb63059111a5bfe3a0000000000000000000000000000000000000000000000000000000abefbcd8a26a06af3bb2cbd1ecead7374948a429ad1807a5750b98fedf58c2eb28378a4068834a041238d113cb6a191f2a4756c819e71355006b4fd3ca66699604fd4df5e4f63bc","0xf8f2820ca9850218711a0082fc7494283af0b28c62c092c9727f1ee09c02ca627eb7f5875ed8f5d8362c2db884acf1a84100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000001e18558000000000000000000000000000000000000000000000000000000000000000f627269746973682d61697277617973000000000000000000000000000000000026a0ed536b66b49d579a8f087c97dd475df277290d988b0a81a8f648c25452feb1e2a024487ae773c504a3a25d69095efb47beac80d55361ae09cbd04ee3bf1abe53f6","0xf8ac82093a850218711a00830aae6094f296ec1921acc61303dbbb88e5e9517a015c2d4280b844a34e7af200000000000000000000000000000000000000000000000000000000000012da6dd6ff73cb59ddc350c5eb8e63be488937e6cc82c0e1e71071670177791230951ba0bad12d5bde452d6426dbb0b20b6e727d7b73141f7192997ae1ca8233dd1b25ada05ea58260f9b3b7d83d59c545221541bea258ae127449752db1d73b16fa9bd253","0xf8ac8207c58502068f770083012b95942b591e99afe9f32eaa6214f7b7629768c40eeb3980b844a9059cbb00000000000000000000000037b1306594b1a098f693612adeb340d99bbff90200000000000000000000000000000000000000000000000000000b54cdd9c65d25a038ccb1fa13a7ad15809df184de5d7eda5e1e2f9ebc9add26dbe5e0ea5791e4eea03bc4d594bb229dd31b5c4cb566ee1713dd9c9a8eba32c713dfa0d1aa52711398","0xf8aa0e8501e2e61ccc8301d4c094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000013b6a458d375c4c0a6bb5213b82f547005186200000000000000000000000000000000000000000000000000000000001dcd650025a0f5cf471ac06b3eb0b3e644c082739410bbfb851b2803028a553949d9bac362cca0435a14db3382fa4d5f66c2427e66d117e9716ab9ae32dabdd124ce3270ead408","0xf90135827ed78501dcd65000830249f094d1ceeeeee83f8bcf3bedad437202b6154e9f54058902c40b73af386e0000b8c45e83b46300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000097a20977588f20eb27c742c91e24725fddda6a34b486761563470cc87c857512cf5813ba2330dee43fc7c23e766ed67429b0961d9e6b9df4ac0c5a67ca0116c9fd65ebd27adfbf6a69cf668d65e4bfb64d4f0032f5c4275d22f4d418e51109489603ff26a00ea72ac216095bce5224937a46f9ca3c952d3d0472270ca4e43b3179ff81852ca02f9fa732a679aeb3f4d5b7916c8ba5f540b707238219ecf12d66d15f4604998e","0xf86c808501bf08eb008252089482cbc94d37fe735e7240c2af8aaf1dd5c4de6d0c8804bd7dd09aa83450801ca0663103f0540300430018ca333ceab04a1c0080b1634c49347f11cd714ab3d302a034fca647a15f4b8339e20385030dcbb1f91e46a14b3a392901e1743fddffc9f8","0xf87083062bdd8501bf08eb008301891b94ed0fafe6846e281b248b1f67a90a3e2728875c018806f05b59d3b200008026a09cde8c745cd157eedf6d1c5dfabced125b5329d19dad7eea63260c5663e01576a016ab3deeed50455b749bbe297f02499819748c38c12a960a7c551444c8887a96","0xf86b5a8501bf08eb0082520894e48c9a989438606a79a7560cfba3d34bafbac38e87b58cb75fdf44008025a043d981767af343e943d2374651b3dd5e5ffd9fa171118025aa2e4e44663f0cc8a05eadfd85e6734f3d9f70334d6e4ef72a0fdb12f168368c6f009acd06c46345f1","0xf88c8302c6548501bf08eb00830147c29461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adc0858625a05195249fe90179ca869d279a548048e24b46c05c122b5e9d1b4a3723f6aa1c6da06d53b3b46b9f325285d85dc39598f5c9d9394a168f3eed2d3adb74dfab3156e2","0xf86e8213778501bb75640082520894ee329451cad5dd693369c6039d45e68bdd4476c888544cf590e01c40008025a0b6b4263519b70a09374befdf713d5b2bd16c0f25a0f3911c1962dfb43402b611a06e46c4dd901aa0dc49ec231bb619f386311bbd410df9f4f3a7ed4d493655ce34","0xf86c118501bb75640082520894835614a871942ae1a87517a7af2cae8a59e42cb88801b679f3a797214f8025a0ddfd7eaa32a33547b40c4d403b3b23122a6e788b4fd12ca20acdb7bcaaf06f90a0361b05834c02c61a534e5c911f1a63f93478a82c6b1c6a029aa8a278daaba917","0xf8ab8211c98501b9aba08082d2d294b149d8c556d888785ad13adb67ed29dc64edcd7180b84440c10f19000000000000000000000000c0232fbd7acee905517dc878fb50c6ae1629a4b300000000000000000000000000000000000000000000000000000000b2d05e0025a02d21d4830c35ba999f622445a40d9d34c8b6a9a33170d26934f6ddf130cbf849a05f079da12b6575de48db788beb36582088fdb77236b0e19b0ca4f5f1135f4492","0xf86b018501b9aba08082520894a200006fbe7718b32cc52fc3111185785614810d8804787a82a0fbcead8026a05f5a76f4caa2f46984d1d454611c0bb6fd571a9ca36cb482b6dfc6fcc0010b7f9f07c60c94ff795e737d25fb6f065dfeb122167e9c441cf22afff37e134a43d3","0xf8ac8220918501ad274800830186a09465c0469fa7a3ceb8130598e90f5f76c11b7e51aa80b844a9059cbb000000000000000000000000a525dea492d3e20598df120a115ee10d43ed613000000000000000000000000000000000000000000000000340aad21b3b7000001ca09e901141878c060c45e0f30c6e7aa862cc99f8989bbb79492c3342c406e92b16a039589efa0ffd423524f047e1056247382f7760bacee246e9febfde63c4341616","0xf86c028501ad2748008252089444284cf791085f6830c31497a0defd4dc83cca018807584246e3bb724c8025a02a9887396a13c3a280f5ef27c7ca738b90eaf0e184eff42cba66ffa913277296a04278e9fe2fa6443ddbd297f7688f26706847e409d54830fe5645763627b6d947","0xf86c2c8501a73167008252089425347464ef9f5a32ea511e6eb13bceb4cd9067cf880de0b6b3a76400008026a0a2a7074b151b53e8bc4d7c3358bc71efb3ef167ba4ce22aae60fb66538b043f7a02bf89d2c507d1f1ffce15dd9f58dd4a4421a414332b3b0d505c34f219a2a4874","0xf8ac831c718d8501a13b860082fde894d1ceeeeee83f8bcf3bedad437202b6154e9f540580b844ca722cdc7774dd0216e565cafdf10776bbee9439ffa75d2516a6138362ce0733f9e8272fcecddcdc0a45a9f143aa1c512e6b730d6747d8947f53d56df255c35f2504e0421ba0ddac112e61908846fa352f7fc0150460764845ae72a649391c5baa94f203f2bda04666ef6ecefc7a448e7b7d76a33f3d13106991d4537f2781f9e6da4cf42a9dc6","0xf86b808501a13b860082520894fe547350558ae6b7589d32ae46f088cd0298c86187287a4f4827d000801ca0fa53053c330ab79d150f5c3ceb025d1887fbaea74b8531f8ef085368fd84f996a07b7c766897be3d79d8078b96f3bc55e1521d0ac65a3dec7a88fcf9e98c8fbf91","0xf8aa81908501a13b8600829538947b0c06043468469967dba22d1af33d77d44056c880b844a9059cbb0000000000000000000000002722c37bd9886294a00c79bcafc5de66592ce36d000000000000000000000000000000000000000000000000000000000a4083001ca06b16b114de4dc52e4fef123d3563e8600dc5f47ef82ae583b9dee00d80bb1cf8a06287aa966567ba8df76eb15075a069b68e14abe6df40aa51ad79b72579392a63","0xf8a9028501a13b860082ac4a946b175474e89094c44da98b954eedeac495271d0f80b844095ea7b300000000000000000000000029fe7d60ddf151e5b52e5fab4f1325da6b2bd9580000000000000000000000000000000000000000000845951614014849ffffff26a09b2bbda2f38a52e55789d5a513b8336380c38b283a03be10f8d203360efaf98aa04323d37250d9d3509e89fab94837c92658542115d55a2d5774f1465accdc533a","0xf86c278501a13b8600830186a094f2dc0346d4b8bd1d7e8188207767504e0d10f65587b1a2bc2ec500008026a0052f03170155ffd35757191c543098b9ee6490a0765a60d43ff2b2ff3924a082a008a17747c14e10e69d73e75047b85541c4c589f44fc5c12484f508a2a0c19122","0xf87183092c998501a13b860083015f9094f4f28f4f29b3ba67e22f735103bac850e71d0656890277dfbbdbb224ec008025a0b7ccd3678582ec1e79a0a57dd030ed66bc5fb3ea47ecf2d171cb57fe2079d412a00e7f456c81862e90a3a0a44cbbe0722b424a39b547cfcd15db8dbdc5da342d43","0xf8a90f8501a13b860082d00f94a8258abc8f2811dd48eccd209db68f25e3e3466780b844a9059cbb000000000000000000000000df837c10b9f265218a117d3f490ddd2bc5574d9a000000000000000000000000000000000000000000000000000000174876e8001ba06254d55f64dd9fa3bc3061859440f09c800b3ad4a61e5f51574da8389b764d7da031dffa690d35694598d61b7ac414d25f192748be31e9359eff325448f918ed47","0xf870830200a58501a13b860083030d4094fbe5ac1817256b016ded3277d205ef99b39d771e88160d4314c41880008026a02c4ffb32f487e65f7c2359f1dbc5ef3342a37acd5111b038dd5eb89b27abd7ffa063fef3e59c45785dc586faff753aebedd57a7f9fb3ffd4f61bb2897725b610bb","0xf86b048501a13b860082520894fe547350558ae6b7589d32ae46f088cd0298c8618734b18b26e3fc00801ca02bc9a16a5170ddc2bd0614a1e810efbc09d2a091e718a36aeda35f0613966faca06ed035d9e47d0e8b57047759e9f339d5c7bc20aeeb7583e5aa59cc82e3cd71e3","0xf86b068501a13b860082520894e82215e4cfbb64e4fa2075fddd9d063b11462bea87bed3787bb4b0008026a04aae7c30eb120b676897336118d388dc193ff5f0e8a9f1133875daa6d7243a95a016d937b3d31cda049f3a3a1f42f460bea7ce63ed62f7a88b1fdf4bad77656b83","0xf9026c81e185019f75baff830aa51a940c651af07dd28b9f8b1fd283bc408d6d1ee214ab80b90204ed02dcea000000000000000000000000480b8d6b5c184c0e34ae66036cc5b4e0390eca8a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000914fc762ffcb63c5ddfb7d08d94df5e49ca984e9000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000221220b79e5dc3cccf37aa744c4c7529dee2d046236b4d671a1fb6713cd750dab4f36400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221220d4302c51c7ada234f2078c308ec546164289f820d7c63c427ccba8fc1d49386b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221220d4302c51c7ada234f2078c308ec546164289f820d7c63c427ccba8fc1d49386b00000000000000000000000000000000000000000000000000000000000026a0c6c6be9fc7ae8f6b976f059943423d43225eabe4070e4e7439e6a9f54e3a639ea039b26e87bf60d86957ddca23cda2cbcbb43c99518b88191549672ebb73e0f95a","0xf8a98085019680f10082a0ed94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000025a70c820721673d9833e084fff64de0ad79fce00000000000000000000000000000000000000000000000000000000002625a0026a013ee28c24fc2742821284c446c51452a7ae92d3e11f7cc8852e273acad7d8fa6a0157261e7238b766725b417bd0d128fcc1cef4beebb74a9c8e5674e301e850253","0xf8ac8204f885019680f10083015f9094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000fb90501083a3b6af766c8da35d3dde01eb0d2a6800000000000000000000000000000000000000000000000000000003b83e6a0026a0eef4ba1bb14b58b1ea8ac74800b0eb382e6ccc52a3a77b3264b77a54b2077245a04e78349d900a3e4917618cfe156aff356a74ca7ed770db0d8ebbc887b494a90d","0xf86c048501954fc400826d6094f789a142e7f8dce675f0c1521a3ce3717bb56477880855e978f2a3d6008026a0b4b75f88cd3e75b4121f27909c97b42c707c90f2680c5d1afe68c244acabdea1a060d50c4c6269ced423ca9f54c02b50842bce5db38ea14ca199e2d961f48139dc","0xf8b22b8501908b100083039627945acc84a3e955bdd76467d3348077d003f00ffb9788058d15e176280000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000526a03df6511c1672630e669d9725c7cdfb7a30a34053ce5791c6566c86137083f342a0236be5cc9044c831c1419ac77cc843e223d8561ab3f7c066037badf68e2bfc18","0xf890808501908b1000830742a7945acc84a3e955bdd76467d3348077d003f00ffb9787b1a2bc2ec50000a4797eee24000000000000000000000000cd8aaf696376f2daa7a80cd2c91b32f8adbf699b25a0acd4f656e3a1f1dcdcc7826a42f13ae45efe8bea3e71cefc809de0949b934718a001c33054b0d44eab6a1bf1f5a2de24a42c2c406c04c1baf7768a1be97ec98ef0","0xf8b2088501908b10008303107e945acc84a3e955bdd76467d3348077d003f00ffb9788016345785d8a0000b844be389d570000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000325a03ddae2974b6a761f380cd575dc4b8ea00e9a012b0d419469466a1bc05c00f3b7a0331407619e31b7cba42ede47ae800999f5ed60486376ce9f58e29027fe9cb343","0xf88c8301029c850189640200830402c794794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000042b921ca023e4742a8abe8da3679681cf52f885f161cbb0aa6f2780097434553c764432d1a020f69a6f52da6c74b05c0f7fa2a685c62407d02c4ca7275fee3ecea2cb3b60f7","0xf88c8301029d850189640200830402c794794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000042fc71ca08db742a2ff6287462aa47b15576d419f1ad2d4f5eb857de77431f2f668c45b96a002a9e9835b9f5a68ea7e79dd82ece2af95fc859357154f47c67186a1091516e8","0xf9010d8301029e85018964020083057a8094794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d412000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef000000000000000000000000000000000000000000000197050486b93af200000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000043c101ba06535b003355a3f90295369c4a0dbf6f0a6f93404752104751e9fb17ad23d8149a024cd88be1aa7f7bf6d8093a2c2556da799c93a95ce31d6b60ce8b8916828b6f1","0xf9050d8206a285017e10d68083011686947be8076f4ea4a4ad08075c2508e481d6c946d12b80b904a4a8a41c700000000000000000000000007be8076f4ea4a4ad08075c2508e481d6c946d12b00000000000000000000000044e9d011df8741be2493e99297e9ad67bb1aa85b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b3256965e7c3cf26e11fcaf296dfc8807c0107300000000000000000000000079986af15539de2db9a5086382daeda917a9cf0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001158e460913d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea3425e000000000000000000000000000000000000000000000000000000005ea7373fd7e6cce81d49fae5ac7183929f9922d6299effd45ff0eabff485e447b4afbd250000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001cabb5b92a6b1d485f4a95e1a9ae0dc3810b55df975cdffcd9a7298d18ed1076117bef55c7602a09449581049a66c6a7b8f9a86a9dd80a20cde8bd873e734d8a0a000000000000000000000000000000000000000000000000000000000000006423b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e9d011df8741be2493e99297e9ad67bb1aa85b00000000000000000000000000000000000000000000000000000000000009a100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025a0b785c33350b6e1019ad23d9681df2e0397793c84dd398a273c9867b578e60628a062996538f80d74b38aeae40108423cfeb52a1dbac110637b95e4b1d6fe900301","0xf8a96185017e10d68082af3c9457f1887a8bf19b14fc0df6fd9b2acc9af147ea8580b844a22cb465000000000000000000000000e7076ad17313c843a1f8a03af86981496f3a5eb5000000000000000000000000000000000000000000000000000000000000000126a08b641488a3b3a3c25267af47edc277ee6dc5c3400b2a6f94362aaa3ec353293ca0074c1be9b4d57b4166582f8e0b530c4924bfa414904788663506027b0042a26e","0xf8b10685017e10d68083030f2b945acc84a3e955bdd76467d3348077d003f00ffb9787b1a2bc2ec50000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000225a074b03dab1ff6b220b92af9debab1b93efac9c92fa8c7c1f67fb943aa935bdff1a02bfd7ca8439316b7967970b72594c1a70ec27f7f6c763f8112e32b4ec52abe07","0xf8b10985017e10d680830c9ea8945acc84a3e955bdd76467d3348077d003f00ffb9788016345785d8a0000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000325a06f8db8a1e385a1e8c79fc67b4ae9410eeea22f75b39e66e374e91ad32586bcdd9f819e942b068e205704a73ec909c11457bd33e175fb696f8a0b344e98d7df4e","0xf8ab818c850165a0c0d3830144ed9434848f3c3934733d3ebc6f82489346592566c77780b844715d0e3300000000000000000000000000000000000000000000000000000000000000150000000000000000000000003da1eaba88cc6199dba96ca5291bb9fe8058ed9a25a0a18849ccba323e3825407e702deff761ec83b2c58ea83b74ef93eb982a6db2bda01717a77314b5496a3fc81ef7612fa1ced8fef28a8cd7ec0c8b5b622f0924da7b","0xf8aa08850165a0c0d38301388094e62e6e6c3b808faad3a54b226379466544d76ea480b844a9059cbb000000000000000000000000e62e6e6c3b808faad3a54b226379466544d76ea400000000000000000000000000000000000000000000000000000000054cedd425a08024e80e6ed797e6225fbb4c3153be3b54aa79a44398c58c09fd9137aa3e203aa05943ec2ff98499d6b4ec533834f5ed467a836a30f5b57713db0346ac12bbc2de","0xf9036d821b96850165a0bc01830281f1946f400810b62df8e13fded51be75ff5393eaa841f80b9030465cc3e7800000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000050c1ee000000000000000000000000000000000000000000000000000000000050c1ee0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000050c1ee000000000000000000000000000000000000000000000000000000000050c1ee00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000077dc088000000000000000000000000000000000000000000000000093a3d4e254320000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000093a3d4e25432000000000000000000000000000000000000000000000000000000000000768f42d225a025edf12ee9914c9dd38043d40f523b9651e0870e936632f42821d3d5fa14fbd9a059c5a6cc135bdc74a31889fad24f9b1c146b692ec6a10b22b4ae0c8ae6210f36","0xf8aa80850165a0bc008301d4c094e99a894a69d7c2e3c92e61b64c505a6a57d2bc0780b844a9059cbb000000000000000000000000478439ce384d46acfb4376b4ef8152da9c3ec4b70000000000000000000000000000000000000000000019120301a452ada040001ba056a50236fed0c279ba190bb84bdeaa6ccaaf972186c302337c7d4ae3bdb8a040a056d61d7b9931aaf070edc9c79a3ab745203c6ca729eab4e3535d51a76efb2dc0","0xf86c5b850165a0bc00825208946ea9090eedce9673f09e1a1ecec5eee6efa5b4fb8824fa34a2040740008025a056ee4c813cab2dee483e3d01a4bac29586c8d465f3737701bdedca4f7a917809a0687b645ecf75cf2e3c5407d85a82a0aad2187be2e3d682fed0e189ec52a3e231","0xf86f8304645f850165a0bc00825208940226a0157035615044dcd69c5446cefdd40b61d28804082f089ca994008026a06155ed27626f61e387b77a2bf188efe93173bfd5df0fef7a700d9583108e8231a02efdc8081c75c1aa822794b0ab01efb97b20d732559fec6d300570893c722204","0xf8aa0d850165a0bc008301077a94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000017d19ae4a90418e8911c4d449abcb14df1f576880000000000000000000000000000000000000000000000000000000002faf08026a0c0052b8ca1e69b155a186251024e14fbde48025824fb0bf316b544e6356e1ecea00d529ad6501e9944f85697a62484799a32b7fb509f1e3549d2573248d4ef0a3a","0xf86e820e9b850165a0bc008252089475c652ad82d3b451975732cbee9442f0460e3ee0880ff78ca9a14d24008025a0e98f7f2302fc5f24ebf0fa9bac1f839667812a16e553cda8a138bd1b2d20edcda05cc893812a3826239c2c95aff610de684d120a10dd34fd6eff66e07ea72d78b9","0xf86e820e9c850165a0bc0082520894e7e256cc80ef44236d09fb330a41b9c8e138d73e880198c1490d6d7c008026a02fe950987fdff13b0e8e47ff538e47094af8cca9987a8fce851cc185d34495dca057d676db8066d39a7ed57c8fa3088fee4f8a3c2c9022eeca3437c54ca7c22463","0xf8a980850165a0bc0082bee7942b591e99afe9f32eaa6214f7b7629768c40eeb3980b844095ea7b300000000000000000000000005cde89ccfa0ada8c88d5a23caaa79ef129e7883ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25a0be539ac9157df94f9e2addb319f101f8230305bdfec7a5e725c7e5b1c408ecf2a051096c82fc0804ed55b79c534959a5289847b9d0803c80e8e897ef2941401797","0xf86b01850165a0bc0082520894722b72a2b63630a67ec9686134b226725c1b8051870912d722b5bc008026a04146991f11a34f94e369238e486d17ebc8f4c1f2394e597eb2e237d488d0d361a06c5fce15caa6d8cb2d23ebcd53163987049ee3d4e6995c976933edc068b96ef8","0xf8b202850165a0bc008301388094f506828b166de88ca2edb2a98d960abba0d2402a8810afbbb4a0f30400b844f39b5b9b0000000000000000000000000000000000000000000002752cbef197a961adec000000000000000000000000000000000000000000000000000000005ea3449f25a0b3300c5bb329cbbfa22a4a1a50817e1bcc798a02b87d4292f6a77071ab8a4901a0265e178a19322c6fb0ec6bd3fda1cd242ff3ec50e7ebff32aab0db5bfdcdafd7","0xf8ac82020b850165a0bc00830160f0948e870d67f660d95d5be530380d0ec0bd388289e180b844a9059cbb000000000000000000000000de0bab5882f9a559052b1de33c862baeda0abd4d0000000000000000000000000000000000000000000000000de0b6b3a76400001ba0de8d7933d60fb2d0d2eada3e9570a460b07c52d1d3bdcc2b18736f3e43af4637a0113daa377b705c888affb67da7fe9720132b903b5fb0cf2d3db92b8d2d226e82","0xf86c02850165a0bc0082520894a87939c16ec943352abb83bb91993651864f0d878801684ba67a0a84008025a0fc5d8db741f2c816cf0f56f7e4519e88f4a5144d46935d3d7a6bb6f737f0a911a07c9435d78b58feb629bd04ef0fcb44324fa7405d0dedff1b765e63a3f9e180a4","0xf8ac82a965850165a0bc00830186a094a5763bf433f2f154b798b924fb2f6c54137b352280b844a9059cbb0000000000000000000000004df0e87514027a97412e50901b58cc9c2c870f130000000000000000000000000000000000000000000000015cd58b3f7aef60001ca0cf384881d84ac25ddfc6ce380aa53e8e8ea6cda6a208a53d653361dd5c3542dda027f80df8ab3b47aa3a5e3582258942e5a26622e079a728975ebc7f63c88ddf5f","0xf86c80850165a0bc0082520894b7f09b6bb6856de1e0455594c02db9b82a4f2f0e8801121f313f9f90008026a08c556abbaaaf8526763ed6d752c605ac812a1e4ef2a76d4c3b48acacd610a1b2a0217d22fa812a71572612fc0ae7acc2f9b04f1b2e8123c034c1fee43fd37cf26f","0xf901b30a850165a0bc00830789b094818e6fecd516ecc3849daf6845e3ec868087b755880135cbf0206a0000b9014429589f61000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000135cbf0206a00000000000000000000000000008e870d67f660d95d5be530380d0ec0bd388289e10000000000000000000000004103a5bbfb7623d2dc63162c517f7d2e00d1d6208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009d859ec812656cdde0000000000000000000000003ffff2f4f6c0831fac59534694acd14ac2ea501b000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000045045524d000000000000000000000000000000000000000000000000000000001ca092b70a75121767cc5e3e14045ae3293fa61a5e31368c988450262954f9b000cca01048e6ce0e68d0df9dc94f6577283657297b84a3ad83ea95a9fb531ea42e9966","0xf86e80850165a0bc0083015f9094232a66745d8ad6573b8df6276533d062651ee0e889056bc75e2d631000008025a0362e2b175947bcd9334cba590e7fc45b997ed844f53a91981672a6babc6f8ef7a018d8396f5f58c96c19e0f495c6081e52dd20f6180a2b46e8a62f1ddd65ef4a75","0xf86c0c850165a0bc0082520894053aac5ae100ef585ba179e4d043a1f7ebdd59a78817c51686734a00008025a095136456a9dd697f1ccec2fde5f6fe9a55804300d895612f3572115ec365032ca005bbbc1b635639ffe8fb34339f509a32f3fd3f7f215ce7dce3485fd84fcc1c60","0xf86c80850165a0bc0082520894ca268846f77ec39ec45598d036aa18d22786f9d388016e3628b89d2c008025a0afe7794441adfec77c8b40ec67b402d2515dda2c83b7ab558d361d58b9a113f3a0381da7ef505b524e53368dca662aee7cfe658e4e73ba2c415d6ba25014b4f127","0xf86c80850165a0bc00825208940145b171129d6c61e1fc6c1b5814078ad6c45ad388071023b317e704008026a0c31c53f3f8410f7ea5181950d2876c2534c81e01bc040b50d118ff6f9a293613a0094a1c627e762223f4a3468b1f05430430506d1e319eb90550f3b0258382d929","0xf86c03850165a0bc0082520894d8847841f90c35161ce838c685b2ead5c571cf858807628bb860f434008025a06b236042bc1ebda8717df8b7a2cd8d97842e7f0110b8b1584c95c0fe3abc9be2a02abf5f54620f68da7210e17761f21e0fd9515713bab617655489ea3ab3e6dafe","0xf8aa27850165a0bc008303d09094b97048628db6b661d4c2aa833e95dbe1a905b28080b844095ea7b30000000000000000000000002a0c0dbecc7e4d658f48e01e3fa353f44050c20800000000000000000000000000000000000000000000000148a9159f116abe9e26a0446e522ca86275dd742974ccbff97537487bdf7bc2bb898ba1a22a4279368032a0134ca9b5f2458197b0b15c3f58b5a8e404f6002877b9a71b41ea7f7ef295d894","0xf86d820504850165a0bc008252089482b398f92dd3851f31aca17a8a95fa4befca88fb871a6cd253d6e0008026a097c47654b19896ed062a99e8b7ccbf33443328b5b7a273a19d060090b945203ca03b2ce2e65c883f11293562ade777d9dc3e81f88b2ab80c86036e99c3b81b7e3b","0xf86c01850165a0bc0082520894a9e8e9ecacea1510d68595c595e1634f553c01d08807640000f23328008025a030a900bc4af976d95dac3dd8626069a29171751c36f4eb0a7f5c020ab74d07cba072fbcc5867d1b46b6930e59416e10480ef3aac234d4692cbb3116a33ed0d00d9","0xf86c80850165a0bc008252089457b4464eb4f91226ea02083f3de57acac6605d3e88067ae4ba417c90008025a0736d20cd1a6f09972ade785ed34cd8153e8ebe5e8b94a586a5ba795fb1291857a062ccf8c4d3bb190c61366af0bb57c906ff09fd8f8b6bad509889eb0d483fa5b1","0xf8ad830297d0850165a0bc00830f42409432a3256a4b15badd4a6e072a03d23404d925a5cf80b8442da0340900000000000000000000000070745fad98d470a9d2a530bf9323171b7f5b517d000000000000000000000000aaaebe6fe48e54f431b0c390cfaf0b017d09d42d1ba0722fadd61fb28375ccccc7f9b24ccfb5477cd6274ac9d5dbb66549303ecbe76da00e6709189b784347fd39cb4770c79b931dad97d68c3a32dc465fca2218fe8050","0xf901ee830297d1850165a0bc008302dd709475db8b92937f8f86213e523788ab9f066efde3fe80b9018439125215000000000000000000000000051325c06f96111298782a3929da28cb78b224260000000000000000000000000000000000000000000000000012be05524a6de400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005eac7e19000000000000000000000000000000000000000000000000000000000000a8310000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d0bcd35f7dc468ae0ba2a93773be02acd007ca8fc08b43c845afcb59857449111784756116466fca053caf3b61a97970268ffc5f8aed74f1c77629994aa86ae01c000000000000000000000000000000000000000000000000000000000000001ba0412d06e69db045642c0371139ab6362f3ac231300c328b7b94ccca35e736b76ba0331ee5bf31204407904bf9845ee150dc977c4f971611d9568706dcacdc3b9d82","0xf86c01850165a0bc008252089470333ce9c74fdece89196f6b2d5f8880dde1941a88dd89cdc99d24f8008026a00e4c9113298f23e720a502fb713fb7a58ba3599695e05dd488b410c61676f58da0594e2991a2c039c01a5e1d93bc68fd5ad9aaba2a9432f9655a5a90c50764e8c3","0xf8ac8258de850165a0bc008302710094aff84e86d72edb971341a6a66eb2da209446fa1480b844a9059cbb0000000000000000000000005a089ea0990cca43a1a74a4bd4f8a08473524c28000000000000000000000000000000000000000000000009d120eb8b477d000025a0e69eeb06fe2b7bc122b336334821449eba2d710c928f1efc4235700a2282619fa058838bb6651a8450dd9c5e4bdbc7e588cfb1b20f8c4ca1efb0769eec3f097e16","0xf86e819b850165a0bc0082520894036ab8ee93a36b229926e0993bba7452b00820f189083d6c7aab636000008025a0d2f33a740e59f76b5ea24388abfafc6fcb5a9292e8fd01ea6572eb222a17028ca0258e6379d14182519c3a607b458063ad005cbbbdc552c6edf18137458dd889f6","0xf86d8199850165a0bc008303d090941d6a916034d12065f3c669725549a6378cbc3a4e87b1a2bc2ec50000801ca07bddff7ec860ac26ac9d0d7fcf3beefcc80ef4c6e9e9df1b5011bc159dd9ad5ca04859bd62a67693c9e117683e493d8e726d01929f3ba336461bed589176c9e5fa","0xf86c808501620d3500825208941a5b5887f0d6fbb8804ef3fd7742b33805e791ba8803d08d97b5d7d8008026a018ad5685e8ff57d4c9ee4aac75cfb1472d7c63ecacb751ba3ea1f86219eb8c56a05d7666a0e10943a1ed958ff1f21825e031077613ac5e5eb738f9972bc4b67c88","0xf86c09850159b4fa0082830994aef93b6aecad4fe1d08c1712db3c4e8eb0e3a839881bc16d674ec800008026a00c597bb2fd1023d0fcabaeb414089a76ad8e94922cc7d7f3c6c8ca3041cfd9aaa00f01855c73075f8e3f61437d250baac62021356a958a9b997a73a3373c83d03d","0xf88b8297aa850154f046008303c58c94794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000043c541ba0b0b58afa6fb18f92ae871469696a2508ace166df657de718bbafa311196d3deca057cf7ede7f1c37156abf743cd5d95b845fab1d2653870e31147ca9e7f9366346","0xf88b8297ab850154f046008303a63494794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c800000000000000000000000000000000000000000000000000000000000434b71ca03df496e97fcdfdd70027de00b26d6dc5ce3b145a573beffe2ca8615c1c1b6597a073fc2cb6d6b1ebb0c28314087966cadcba2b3fd614d6c84b5ea7a05e445722bb","0xf9010b8297ac850154f046008305442294794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d41200000000000000000000000000000000000000000000002086ac3510526000000000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef000000000000000000000000000000000000000000000000088d3656d1eac858000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000043c3d1ca0733745a44f38d529e17ddc022bab257b9c1f3087fcb222c7a0094bf39f53cc299fc7c604d99ec80d04055e4084b7c5aa46119a53959742fdb75a030d490a1b7d","0xf9010c8297ad850154f046008305295094794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d41200000000000000000000000000000000000000000000000006e32adc59da7620000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000001ea0e23cc3bc3c4fcd0000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef00000000000000000000000000000000000000000000000000000000000000001ca07ec14919c68125fcf2b22e4bfb62db1361e0d3ce7d6825013f9d974beeb8c5e1a0161fa80341a09817ded4f3dc9ecb370287fd7e4de1b522242bb451cdcccd8313","0xf86c8085014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68811e569751b3408008025a022d0052ffea3111391a63357b454a8da67cd3c0c2263a2e6ced3d16d288c0b49a04f48141f57b157bcb5effd57074f84da13c8454063dc7c9a43e3c6331f74f095","0xf86c0785014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae688a48ec234949560008026a0218726a9be6b0813d40fb59a2b64ff9abcf7b5f6c892ea738282eef69f59d57ba0050f6320067f2d0a292b8f87b7afc4ab447487371d9782ef1f8eace8a63f179d","0xf86c0385014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6883e72cb9558fba8008026a0527c7f45db3f884b31bf8480dc75de6526530b1773811c457bca037eac256074a05691bec7343da7b3c696b868882810344d41a4a3a3e0d8e33385b4499dd2430d","0xf8ab81c885014c980b00830186a094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb000000000000000000000000e3d356f09f44a395007b1d9b13acb35c010ae436000000000000000000000000000000000000000000000000000000000007d95b26a078d943948e46b61e28ca6e393b2a0da897fd8b49705e6bc210d8c1d3652143caa005d9c04385ea5bcc772e121e840019733dec3459c27e59ff032fe14936ec5a87","0xf8ab81c985014c980b00830186a094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000e3d356f09f44a395007b1d9b13acb35c010ae43600000000000000000000000000000000000000000000000000000000000c139126a0fe05ddd0359a69c03abe61e9e5d5cb31d2c6d25521a11cd8cf8dbdf3bdaefb33a0635574c3024e017bfd90f4dedf358d81edec0964faf2f2d5c7e7ab9b822de819","0xf86c7785014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6884e8baadc540068008025a0889d2d18cd48a46cfc07ffdaff7e9fa9be7d5fc38645c2ce9d987874bfc6e514a00c20c62856948431c076b899e37f4154ce0616aeb9528269d3bfd3bf23d476a2","0xf86b0785014c980b008252089425ea4690e4039e162c9a3acf002e4d984ea45106874b4f5eed7f4ffb8026a085740ecb2eb6ed57245b67e7d79bb14623adcf40050d684530f979d8931e6c07a011b07ff9747aa2a161a08651fabc5e7f0795b4e0496394b96f8b2fb475b63483","0xf8b4820a998501473f9e2383013880942e642b8d59b45a1d8c5aef716a84ff44ea66591488034d8b1a4b53f9f8b8446b1d4db700000000000000000000000000000000000000000000000da933d8d8c6700000000000000000000000000000000000000000000000000000000000005ea3440725a0ed4b6a4b2a52ebc91ca3cc43da62da33fb09d0b27aba2c60dc40ff1be0d26081a0631627863c10073cd9240746d35da164ce00323a188390825b55373bd0093e36","0xf86c13850141eebddd8252089487e90af244cc01bdc9aeb76e3c35e81255470c198807622c11947680008026a0d89193bff77e8117c089ce46dfaf83d9433c98a2f180b51c97d5f6afed56e88da0125a28c858716e22eb2ac08bf4d398ead0fbd05525d8b05611aba80282945c1f","0xf86a01850141eebddd82a4109400f0486a7d3d3cf0aa08b04f36b84ccb7fd575568616e041ee4e30801ca08d1e2fdaa6942e4ddb3cff6f9305f3210c5ce470bbc1baeaee0f9b75624c59e3a060ec0e4918b625557a4a0feb9ba120dd82f1b963dc1811bfcf834d2df02259ad","0xf8ad831b0e8d850138eca48083030d4094ba50933c268f567bdc86e1ac131be072c6b0b71a80b844a9059cbb0000000000000000000000001ea0c8afbae8126eab39cd7885fb30492cf430d30000000000000000000000000000000000000000000002a9a34dcc17c1b8000026a0edcad88590bd9495443497042957277d748189a205bedfeec663144cab438e35a002004f90f0f1ac9186001e5a69ab9aef27321a2f05955efe618860d49a483e72","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880de05500fc72e8008025a0d11944ef64d4d999aaff9d6442eb15b3956bf1abb1da0d7002de95de7019dbeea04d5ed56af376abad8f571208f26cddc9024b74cead49f2e93d6b589181380c8a","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880b207eb07426ec008025a05aef45bc4cf9c1065226880ea7518d7cfb6c56980de672554d3964ecd4a13281a0634e948d235364ca0d8bd8c471165a0c2538523039a699501078ff36d3cbdc47","0xf9022d8298e0850130e0b4c0830122fe94ced13f21d59d6caec0d4d0a31fd6ecc67a20317880b901c43249d335000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4538374230363438353034303130300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004375714f414e734d61484375436f7a39717a65354252616f744372452b7048544f3138734f494e70616a56383d3a6734705a6b49726e466f384e4664494a4f6c3232316e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000494b594f325a592b5a3374662b7a4e315868792f464b6b7a78316648513339752f4f74386f557149787148593d3a41447772657367696235345a36324e2f72775753306f403333393333000000000000000000000000000000000000000000000025a05d8006c088ba727a22414a1112b832a02aa3882367bd6454dba0910119892cc8a00de29d331ca890e835cfe4d8a8b88b347dc8c4a5d7894e29f75d6b6c738a12a3","0xf8ac828688850130e0b4c083018cc294dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000003fbfc3d00fb29bc0bedd30873924810e4bfddfc400000000000000000000000000000000000000000000000000000000016e36001ca0f8c3757396d94623bc4ef9e42db00311f110749363a68f62903ab0300ea88676a0289acd20d2f536651276845ab292bb0e6a3c7fac62dd4b515dbb96af73d7a29e","0xf86c02850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68806ed55ae1c9218008026a0f194e7e78f71d2a1a838dc0eb98fe85fc939a95797c39f4fd65543ea468ee155a065c12a094117ee97ee76aa946057457fe0ac23d6581bd90f7652b5ebabebb15a","0xf86b65850130e0b4c082520894cdbc6acacc658b45bc39a23c6676b23fd67b3167872eb2c0da9edf008026a014ae2955ecf7732f3316625f9991ee2fd6660263dd46eed28375f4a5aa43bcdca047179007de6108d91b6c7d4812f2224e546e4e353dfd296d2c53c255812c60a8","0xf8d4821c6b850130e0b4c083030d40942e642b8d59b45a1d8c5aef716a84ff44ea6659148829a2241af62c0000b864ad65d76d0000000000000000000000000000000000000000000000a8eabfc78526fa9d00000000000000000000000000000000000000000000000000000000005ea343cc00000000000000000000000034ebb9092b9fc46c7c0b285ec89b9811e8d6a1f125a0fc6607ed07f2fb1f5d8c97a83706eb799d9cd60691e934b43aa42a382d0e0db0a03a1fa62bb444411bce8bda2a65361a1e5a3984d2f3f7f1970e95db709b65ada4","0xf86c0e850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68809fd927cc356e8008025a003226094484bd711bf77d97f9da09fa4043005f68a5b56979ec1927b8e0c0988a040da68c0a7affca5fa55b8b36c1c11fc8c85d9e87cb01d9e9c4933a4097af2d3","0xf86c01850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae688070dc0231ca99c008026a09a53d068df20921dd40a14c984883203270894b266d25b637d74b468147b0f0aa00b67da286bc53f0744a85419d1bf828cdffd80eeb5e4d49d38e5739f87e9eebf","0xf86c0b850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880c7d0f889ee8e8008025a01f6c4a5f495222ec0927abe0b001fbc056ae4111751aafb5d6378b9c850d1500a05541dde05029375027f54d026fc74e48ca7a6e986c495d9bd1cb758681a3648f","0xf86c08850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880b0b9415ae44e8008025a0d2f37d177dd6a264436d0013c5fed3678d141fb4fedddd1a240646c9f0ba6460a05e9a5f237acc7b9ae86ab3cdb0dae4971c541f93ad36a5e2c10add0e7ead4134","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68806d0c724bdc5f0008026a09b934d5b9b13a0083b6758c58cfed37ed8593581639e5cf55f7bbe652953382fa07ae72426c894e50ff0a8b94e619a1b548b0483fafcd1168f2fa6bace8e56841d","0xf86c11850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880ca2e84ed75498008026a010329028e975336f76b47a9cedc0ee640c4dd19b890d42b6833f502d15a1c399a0310de8a2b06ef14d4eff7bfc364e10f16626f25414a8ef8658bd6471b495c5b2","0xf9078d82ef2885012a05f20083023dbe9461935cbdd02287b511119ddb11aeb42f1593b7ef80b90724dedfc1f1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000004400000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7e4171bf4d3a00000000000000000000000000000000000000000000000000000000000022146594c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343a400000000000000000000000000000000000000000000000000000171adbe5c8700000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006600000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7e4171bf4d3a00000000000000000000000000000000000000000000000000000000000022143505800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea3439900000000000000000000000000000000000000000000000000000171adbe0c3c00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f45e793753e5c92000000000000000000000000000000000000000000000000002b5e3af16b188000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343a700000000000000000000000000000000000000000000000000000171adbe351f00000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0d2b3266518073de150234ee29b34e74d8333a83f6e98c2681ca3f1903d264598a04ed2cc0972dd834f05d7018e66480b5e40bc260461c118049c9b35ba01d3ba21","0xf9036e83031c7985012a05f200830119419461935cbdd02287b511119ddb11aeb42f1593b7ef80b90304dedfc1f1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000998497ffc64240d6a70c38e544521d09dcd232930000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000059ce129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343f300000000000000000000000000000000000000000000000000000171adbf945900000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ca0056b1d709fb718fe746e782c4319a57eea7d36ff000a3ee3c0717609d4c1a186a03a72060940b046403afb27aca5ad3eccfe72e786e476682ca115def0db556224","0xf8aa8085012a05f200830186a0948e870d67f660d95d5be530380d0ec0bd388289e180b844095ea7b3000000000000000000000000ff8e926d0d92b5da930f5534a79e5b821f719f8a00000000000000000000000000000000000000000000d3c21bcecceda100000025a0cf0599d667d0f637eacde685207fdbed082d57234ec09f367753ac22b8f1e542a07f276fe195b69b55c353dc4a20edea7fa1d69583810788386607297da7098463","0xf8ac82022b85012a05f20083030d4094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb0000000000000000000000008d8516b501662d774237355aca1f3c56baca5612000000000000000000000000000000000000000000000000000000000098968025a0241328ae31b69645de0854bd142641b92b6666f629ea1778497d0a5197c64aa3a01cb213d36f747002e0913e83b5a5476ec09030e1c44043408cfed22615efe028","0xf86b0285012a05f20082520894ac3e543d1ea0bbfef0975e60837e802199a7404787038d7ea4c680008025a0a2f95712afd16177fa460c6d84893ab123ec08ab412b1d348c595a5bf047032ba068556fedfb8a7094b006499514ba4c2dd1d22abda6c549ee87ed066671ab76bc","0xf86c0885012a05f20082520894797dbfab26308010199f0b18c97c1c554dd119f988023539c0512e18008025a005ac984be4f5552f0e90ae50675e402312559c6c8cddb7f82ada27aacc6b8883a069fbf4ad8567d6ad8b797c1e0e710f30dd6c659bfc31e3305e2647628e9e3ed9","0xf86b4c85012a05f20082520894b1793c313cc6bcb656ffdcac736f9f3f009afc2387038d7ea4c680008025a0ec2a48cb1c07632ee0aa3b816e5db25f10af48710f02aa8421f186393aacba04a06f2272b7baafaee865c82e5f7b4550138ef2b5ce3cdfdc8d834dd39eb44638e0","0xf86c0385012a05f20082520894c180e0f1300c4d9a76804d9aba7943b8956e059c88013fbe85edc900008025a04e1c1829eb7764eda4f827497d2bdee68150bbe3feaa7af50a62504eb2392d3fa06bee4a949f6611330f285c8372312816e8ec3572168e3032d7c490af9ee2503b","0xf8a90e85012a05f200828dc694d341d1680eeee3255b8c4c75bcce7eb57f144dae80b844a9059cbb000000000000000000000000a3dff789b8ac4ed21927bbfbc2ee327843db19940000000000000000000000000000000000000000000001a812abac7ddfb6e6b91ca0d708a403634a643746c4823c8837a30ab3531a44d3c4d28af322ecd7a51f98d0a05100866430802fd08c4ac4e1588654a203fa251fdcb19c0a2444b1ddcb84b2ec","0xf8aa0285012a05f20083030d4094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb00000000000000000000000068450d9b6d5d3d352bb2e632083808ddc7d09f720000000000000000000000000000000000000000000000000000000005f5e10026a0c58236a95b6ff5ec43f980922dcae557058530fdb3910a1c6095b44910a70a53a018736a1bae462947927b0b1cc26c25d66fffecd1d2b1df3b17815f52247deda6","0xf86c0185012a05f20082520894c75804f4b0c9447a3c55ed5cdf5f2cde42c2302e88016345785d8a00008026a08ad07e33e604963c3ca221ff4ffcfa13e9c73e7d180b8dbac391d4adba03d225a032ca129db619cb8891c7b21b39a035fd7813de24d56a5b14d50b285e7b4a1df9","0xf86b1185012a05f20082520894ba487bf6f05b0d34db31617170d3c463baf588ee871831fc5c265e458026a046bb7c63786b51a9ca0ec7cb9ad8ea55acc2ac42a1cfc8a899f27170de1b329ea0399db1a294f148fffa3c726676933850ac6b96045852a5c95c16413956273fcc","0xf8ab81bb85012a05f20083030d4094514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000ac3e543d1ea0bbfef0975e60837e802199a7404700000000000000000000000000000000000000000000006c6c9f3f601961400025a0c178b6c11b06ef1387bc53d193bb9eaa83f9ccdacf70a0d8f877867d93e32ee4a0489d61acd72c70f2a53d691172566fc5aacc99140c2698e40dfc207a6f491775","0xf86b0185012a05f200825208948d8516b501662d774237355aca1f3c56baca561287038d7ea4c680008026a0eabf0fcab25a5a1c14860615aaae566acb6917e0d0c7b24345ba0e98a2aa6672a05ac1ad6fe424b12f068e3515eb4ad131dde4bf39e2a30f2d85242b21be349c90","0xf86c0285012a05f20082520894d5fbda4c79f38920159fe5f22df9655fde292d4788102e9c1a296edd738026a0173435d0577300a279f0681fc8900ffdd202d592798a14044751414bbf52ae21a04656f95c4702d2e10490b2e4a88be781cc00ae72c12943082c524baee47d6088","0xf9010b8216be85012a05f20082a921944976fb03c32e5b8cfe2b6ccb31c09ba78ebaba4180b8a4304e6ade74138d0a668bfa50b16d4628865b94618130db944e48326a49d17f23be3ead1100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e30101701220b7add76198a03a31d015fead8a17b930ffc7a8bc8428a02a48d5746e9578cd99000000000000000000000000000000000000000000000000000025a0c147ec8d741622c2bfee163d59ab0dee4866794fc816411965def3380282a301a026b216286050e7347d4a4ed97bd9e2be015c815dbe1a4d6e19f63c28f2b15b2d","0xf86b4b85012a05f2008252089468450d9b6d5d3d352bb2e632083808ddc7d09f7287038d7ea4c680008025a0db5d888aa9f844b2566bb608a13fa3a7a586ced4ecbfe120a113e9ba9ea9c18ca0611c29cca55e4f3f99c4afdd7e5b89f4aa88374ed439d7b96a1c9cdad40bf3cc","0xf8aa0385012a05f20083030d4094514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000b1793c313cc6bcb656ffdcac736f9f3f009afc2300000000000000000000000000000000000000000000001156cf785cb0b1000026a05c1289647a1fb85aba8d3d9f8c19a9a17bc562dce4db6d95c5a3908263ebaaf6a016edebd84fac5df1e75bafcf180a80b4f4922c13842aa4b4853f2f54300b998f","0xf86b2885012a05f200825208940ada51acc249f6a1b320be335527b127d03a9fe887038d7ea4c680008026a0b98633766bbe61e9caf0d5dc01d22ca50d305f505551e237b3f64b83bfb6c726a060f71d2d83df97cbd8799e73db215fed9ba9e5cbcb0206ce89b46c00a471dc2f","0xf86c8085012a05f2008252089485837fb5882e36d054ab518ba2f951aefa7815cc88570fa87381a268008025a03ba379ca7dc36169a9c35e7259d735c36abba5fbd33a2e517a05578310581f79a023fbf0aaff2ff671696ff5b9cad09ce589e7896337ef7040df4d802ffba9895d","0xf86e8306dcc6850115295e8082c350946c94ed48e15dc68c56e2c146239a3b39e5ba41b9878e1bc9bf0400008025a0481c6c8ee6991a43aec2bfb78cad55501b9fbc22ea3e9a9ece44e51bd585245da067bbe9703eec584d67b69efc960e28c1c06f27e82c883188326adad243e80720","0xf86c8085010c388d0082520894015f369c8cdfcab34a2ef4f448e0145d86a4e5188801cdda4faccd00008026a0b04fa2f0d8f6af66b900531f12e05a685d532729135cf11af5ed278c9d5892b5a03d4a543408d3ec1f84e5fb6834ef21574b980d86d8d2f00f5519c456bbb1bb6e","0xf86d8250d185010773d9008252089466c7c8ac1b9680a8abf07ff03a9e637cd742c0eb870197bfcd8f9f00801ca0f2cbce7d1e2124cd94dd11cffcb02daf8413bff952d551e97e0f7a0f3778570ca04f0d79cfb4a9709f0fdbb7bb073e7704e8723e3b990009d3b6ed15bda62ce9a2","0xf86d827dfa85010642ac008252089449d148b76ce691db6243836e8cce651b846ca33787071afd498d0000801ba058e07c497f0be5c91643a43b5e780a4760b34b6df95d13669302dd1506f8dce1a04b4f140b5b3fb36f07b44dd12088b5ea46a6608ffccf1cff1493f2464e131fb7","0xf86c8085010106978382520894ac54b0f52f314f1efbef245a5416fd5d7e381b7188017896703a310000801ba017f7a0e897474e671e1b0155f725d04a15442bf2baa2280162fa180c6162afb2a00264ec07ef2ff50a419a6bcd9b4384347c8d6091fd937ac905596f9aae96cfae","0xf86c018501010697838252089474381d4533cc43121abfef7566010dd9fb7c9f7a8805e1b5089f4a9bd0801ca0550e0a23b9852355f1b551a6a80888ba0c72c89b4ada3b096a9cffa44af030dca02a3888743bcd0eb372a99fdc458d047d40274bb20accae5175add1b7e03b8720","0xf86982cec484f8210f2082ea6094693c188e40f760ecf00d2946ef45260b84fbc43e8084ea8a1af01ca0f55050bd36cbe68870765070ce57da5ac12ba27fe6bdffe8827b31c8c259aebfa04beea357135e2a6abec635f67a7559f02a037e6828f4f4d18c651044082baca6","0xf86d82029984f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb328803c6eb14d70da00c8025a0afae89a75d02056fdbf34f7ca94dbd5013f895d2eaebf70a6625c8494315e487a05c60dd0a235da1e89b3fa5f01b2c7f9ddf14c66b972bbf94f578e0c2c2a35e1e","0xf86c82047f84f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb3287d8cb359b3b99e08025a02c63acd03a982f0ff65ef35fdcf6a167c05e7e66519eb2c6e2b216c3084b8a2ca05cf9ae52116814d0d8b27be4eb6625db767a3cd7aac3203d92e8595110ee54a0","0xf86b0e84f3e6f70082520894c2eabefe82d16d90aafeeeab800504030e01aa69880131888b5aaf00008026a0accd356e5576a0760c632cfd03f605d660ccaa5174c4e2c391babdcb624c88ffa05a91ed2c3b95c8c7ffde91a3075c29b3a177ed01917168122393d8c69789d5ac","0xf86a818e84f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb3288010baa6ef0d8bf8b80259eacaff80ee360ff701064d1ce214ec2daad7281bdd7d4e94e73a53159af5aa0743fe78b9a453099fd5c30470fb9e219b145ed89eba3bd642ab81b649e5a9db8","0xf86a1784ee6b280082520894f6888a28d242cc547896e5fcfddb73519c566ccd872aa1efb94e00008025a0bd604d4c7332190c39f6cd626d3e9f5fe7f71bc54e10f5b491c5eb5b4ff2e1eba065f91c5fdf37f193a50befa80656d04ba22b406e8dea3f8178097912e96bc7d8"]},"version":"2.1.0","currentBlock":9937410,"lastValidatorChange":0,"lastNodeList":9936896,"execTime":427,"rpcTime":423,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":{"author":"0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c","difficulty":"0x7f342050eb05c","extraData":"0x737061726b706f6f6c2d6574682d636e2d687a31","gasLimit":"0x98961e","gasUsed":"0x985344","hash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","logsBloom":"0xd46459b901035b09020172406000521420cd1102069010580501a9423a2a840204188330d1300a000090a5f4a3230b145280951b2808064180209e82756e562867626ec0861c45186884cd4b05007b3aa88280ce8a052482140a06ad077c7209da2103c0023804cac010e1a81dab0a093ea8725a84a629002ab03d3522a107612c0450404164801ea92f8668b7020a6d0c0c85400d84256200c1c89a4a360c548f4ee99100402d450d23439601fc9802d0ce088da44bc17000eb04931cd6535e275a432209d04460259250406422675428095336e898240180240091324478042890a02cb192d00c301288b4680c74b41a046042c8882a82680095281f93e87a","miner":"0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c","mixHash":"0x7116e0d21839194324c008c7a63d5f039bddb9f46423298fe8872291d4857504","nonce":"0xa6702fc00021d7fb","number":"0x97a142","parentHash":"0xcecddcdc0a45a9f143aa1c512e6b730d6747d8947f53d56df255c35f2504e042","receiptsRoot":"0x96518f4bae284a23f124f289f1bcf206b2ac04e8b244ade5387d6de36e62a857","sealFields":["0xa07116e0d21839194324c008c7a63d5f039bddb9f46423298fe8872291d4857504","0x88a6702fc00021d7fb"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x896a","stateRoot":"0x8a1c0af419b0ecf35688627b63cd4523629c737b465f203c2df17ad4c7561d31","timestamp":"0x5ea34392","totalDifficulty":"0x3344cc1c9237e34865a","transactions":["0xda4d70657451e1d3bbccd7308618437a4bd8656f04b999afcd834e4b347ca98a","0x0d380bda311c1031a8accc15b28f75e124b822d0de4e19000a10187fc2c1d24f","0xd7fe9eb19c36d12ce7586edcd483000d9865ccf4d0f25c8c90cb6580baccde27","0xe85325aee703f102edf9739049aca75101165193f9b7c6b4bca81651adcf3f9e","0xeb358c899c0c35fc352c749dd09a6c433c3fbea96d60d3c07fb7f1c930208707","0x37254c2c66808a320c74dac5ae8952a3eebd0e5b2f77ed46f2eaccd76b0d8e9b","0xae64e108af0cb862a77f29bc9ade51863291144922b1d21366871a159b6529d9","0x2d1b323fc01371b01937f21a1ffa02c9c599ddb61d3d6fad661d84e9386385ad","0xb18aadd40d6385cad7b2e4677fa4d3ff81e496e571e3cc9e12a89042fd76e115","0xb7fca2759de79571c473475630fc10ebfe42c70c6d1ad070fe56edf6988b12b2","0xffebbc7714d9eac601a0363052d59fdb610f12d30c00a66c7d52ee108b380945","0xd96d1420749b485413a966c86cc2423d6c685180e72ad896f6740609e50ef2eb","0x8ffa90dad17fd2c41ff4904fff4b2043e8c204dd21168c4bf04756e82140edff","0xcf77d659ac62fad6d638dd7d44de788c44419d3796ee88da1b61827a929737e1","0x5b4b861cc70b54de79366335d731de31a69a16c91be3fd7d3e8948fcbd15eadf","0x8af0fd04d8799b438d28af2b67bc07c41335b757a63ccbb7664509ddd9f1562e","0x30e2517334326440c424636f518bfaf73f69e52851a33d2776b7bd6028eb8e4b","0x55c51631bb8e17f6a4d7b41bbf9db2e7e8c77b79ba350fc400ab396e4e78f2d1","0x4fc097c6bf1286d112d36b13aeb421a87978f2a871087f47f20c37e714ea2885","0xce750d7fc692a4681f22288030ec40b5427193ac1b816e8af2e46e4126167ed8","0x22f35570f3b127971f23191aca3faafe7b247218bf49ca8c59706a8e9c9c7305","0x12c1a271acc9fb36c455e44571ca010aef9bfae0a5637b783350803f8ddcf80e","0x96f70a4377bbe457715bc102ec0d676cf0a83485cc62c3e9bc6cee793228f052","0x016e5e2103d7dec166cf0dcb3a3e5f815e2be69cb45acd056a1c2acf2b5a03ae","0x7a71ebaec48e2e65082c242da4750a963ac81ba618f0c192e973761a64f09f66","0x8f0b8ea25c1220e9126c3477607937de8ea7383cdb6afc1753e0df607c8ed8e3","0x4813a64f3872ba1952c6cf90288b27ae3d6d67eb13870eb9ceb2171584641ac7","0x405d3921180489fb981422d81116741e360479d4c67b9683aa1a08dc96a5b9b2","0xadbf1507cba869109a8e3a16a3cd39776ee4f21ac52b1ca2a0fe7ca2311a8911","0x1e01e0296513cfed8040dbc9bca26edada1065299dd080316ec1ee0eae19006d","0x6520876f392516b966851ebd3dee2a454da24d0900d191970d906a6dad7e93e3","0x669d506244f143e5e4739101e18705340749b3a92935f95bfd73dfce4bc9c8df","0xe9615b5d441a8c57db93fefd1204d1d368d206284b3a900c1fad62a82920edd6","0x78c4b8c32efd5f3c6547f932e0e85492ed5efbdcafe4b84c20457bdf6931a579","0x3617af71c66f4394ddaeac7416e48b84cbc0f0a839c1e6d7c422590e860ca9cd","0x1aee1cddcdc8dd49731cc2e6ef86063ff4fac9d692656e7c374900767a305d6c","0x7383dc4e171d1e36716af774f627f482be4e9929c8e6c6731402da0fb291c034","0x1656e294eef8b83937bda72c86b8af9b6211cd1132a409b0706998bacf10e182","0x40a6dcb604211f6c88f85e85c1c3089fd5aec3da66af63f5ff0365b97198f86b","0x1328d611d243e13800fc4420976d7b0a28cd4899bca11d48394c7e932c84498e","0x78b47ec8f03e09753f2c23d627093e285ddf9e8e22e4cfa44b8cfddc9c9145e0","0x8500b05b1c8c758abdd261ab4a1c83885392bba558884d65f3cf4d7dc52b70a3","0x3b55d74ae0c2ee22b4f47792bc231917204d49d8e53eb02fdffa783b77cf8475","0x9d081f0a6212dfdfa7d28f36a04894ea53a777f7086eb9001efa7d79a65c74f1","0x7ac084eb58e08e38c4d2aa01a338864b994e650431a326957c12a3f5023a4ee3","0x5e15a324f4605aff5f78835bdec89570d76762d559de1ee57ee084e148a8b328","0x6d52d78a633d387bb2289a11c8a07d49471c1414d9556b164083b248419eb5f5","0xb4892ebd00756b6be7ef887fc4174b3be0fd8db29dd0893d03a54e398067775a","0xaa1deb14698df8317c5133d668bd7a1496c50af3625bd642f0107d7c41e3deb0","0x4c900cea8c7c95d1a8f86a44421246c8fe96ace9b174bdcb54d7acd402c4ede2","0x71c6effbe429ef4863a25287099c2cdb8776b1c03534c4664fa5ad8809319f0b","0xf71bb8c054bf2c9f6b05c04785a85fd021d4425dc939b1cda76eacfd152c076c","0x2af3a7401ecc3d088ddee0f5f68bb4fb72958b66b1fce7fc03f885809de34224","0x9f3967efe5301057a303b9d088fd48ab9dc9e278ade04f92940918942cac9058","0x6f355af61a2fd0c22c512478d3919272717b4431c75f2084a5a2b7e8b9d47412","0x7fe1017c86556f3db357c27db88e92510389f5c0946c1cc771f61c65160476e3","0xfce5f2aba2073b4dc6f6929d6ec4390a891d383810523e9eb2796aafdb9466f6","0xd5909f7b41bc3a5b7a7e1d59088cd11c585d801f735ea03553850c2f2668a38f","0x9e65a654a4f15272a342b3730888130076fe53d2b9cd50cb807790abaa849706","0x7f1116febd43893525d9b73a4c821192f6b90d5dbded75e5cbd4cfc462d074ba","0x0fd878c87342b2778ab3ca56e2bc6ee7da15e028b6a8cd3b3d0edfbf68f7ecdd","0x48eb84632adafc36ade5f4497e16db58cc07366ee5e855803a6043c10829f1f7","0x1f34add5b3005927c7be79b08d87e243862352991b5ffddec20f044bec27fec9","0x041a25297b9cc993f6ab06b229697ed9dabe30fb31adb8b7ab842605a462bf7f","0xd47c8674d46db513ba828ebd43eeca67ec68d822cd6d97e06ccc7889b4d1f0e9","0x464458396634d3c39f6b48da7eca8d5eec03065d9f3a3343eac5cb6b1a89176e","0x89ee2c7c52bfaa9b861cd1b3a2802dd66b0b578b269d68f010603a55babe6c4f","0x76d7ee8fa047b39ba9e513515915e92fb4473d09f5bd138fc2148f6a9593b495","0xd6ff8564531530c811345a1ae0ee6fa285e89b7fc301bcfa3fcf3f67a4dfe7be","0xd331f4318c8a3944226976a5b5c2c4ff7769dd05bf442e321df601be32401db3","0x16646dc4a3941cd099553f8a875af9a545bbd20ccbf33cbf1fa91b1b8da96724","0xe92d42a8b035476606677df876167ab28cb28f3e43cf5e2596b12bfbad70761d","0xa9c02c3187c66d785fb05eba9a87bc06766088596b2a48a669f07ee2f293e705","0x2239d461a356b9813ed7fe5c8816de9758dc3e8eb4a8125956f5b622d2db4dfe","0xb44d66658e6cea7c4462f04e60873cd93932b1eba5d2754814589eb55bd91065","0x9d3d93d54660163e1a2ea54fd5f4318fbca0e44d399cb1cc10381e02ec0e1133","0xd600a3902e864ec5002cf321dc87071b59de4cf5f440a64e7110449b43818445","0xfacdc420d5694ba60389961af6cd62ec0649fb91aad2ded908dc1b239055e8fa","0xf14bde434f78f7c4bf3421cbbcbfcd3ac8803794737310451a6cd45b8449c98b","0x56c2e0f7cfdd41319cc844307e74cf2880a4dd3b8a21d63bdbce57c62457d7a4","0xbe662e01df6f6a5d784483e5ab3f25837b79dec311ee8f1f41d76723e774b756","0xabaf9cf9402d9572fbcab160df9f4be8555c4eb71075bb4f5124cd6394bc8eb8","0xe3a414622d90ef9f7d5ba092d7410645f0f625afc3ea10a60d693b0a8ec6c039","0x1bf4854e5a420870dbf5f4f55f255b3d657143e5ca62f05ab9fe94d5ec18406e","0x8e5b200369ba196eb48e646bb94eb0d75cc4125bbbd8764861cc100e7068cf6a","0xd7b72c2ad8fb5381612d921b38af4c73b614811435ca2ab0430b5e8cbe14b45a","0x4f6c2ee4352f4306526e42caf728342b91f10c1d95fb7c4cb29e727d44a67422","0x9fcfc83f5cc423c236bf2ba5d871f1e1442bb01ac683254b7c15704689894a53","0x799952ef892b23128f71569f9b80970470377e93627ef88888e0a67065b5afa2","0xe4128e9c11495e7c6a8c371fffe9d01b3e159caf3dea5c71f1ca3ce6b5e18fed","0x76027cc5b54b8cc5cd30d863839359209c069222b20cf57894c9909ebb1b4bea","0x711ff2f604aba7686391a2abfe5c3c8d35950d05934cb8dbb9e47dc2d0135b94","0x726959e8e07b3808911becd8d0c17d45ae5a5f45b36c8100e927a5a6dd5fdbfe","0xfc0af1ae4a03accb452ec88967de5845fca00e28b21d2f23cf4e99bb01a2cad1","0x07286e57ad99709ffd946ba35a19c4bbbf20d12c0b030ead926381e73e01f0e5","0xb51ff90065c7b245246a4c1cc0a1f66c49c6c72b1d37c56844f7b22ad840cfeb","0x6fb862ba12d80f0d45aebe1a22bfdcf92a182552c4ec412ce088ec3f2c8e755f","0x02a6920664c9f8828d23c17ede9b20f142949613aaeded0ac5e14f0229fb9eff","0x2dab9cce0326bb313d1b43f69902ca7e8a2885cb19e00ed112285be436b8dff3","0xf1ea7f2fb51e426c6e844534b9a61f4ceefa1c6e907a0956b69c5fadd29fefa6","0xd2e634fe2fb21e917e021b84634762d77ee91e1082bfc1a6fa3ac893e7750548","0xaf453232bfe4590f18e73cd8a683130a7fe2949461116714727888573a201f5e","0x33c9b30d68f3ff547803af3304b2b6c5e55ce1b17c7f5cd1242e69457198ed67","0x60fae2540944f5f5f2bce8d5c7ec2b2304f500a3efd2266647f17e07f4dcdfb7","0xdb48b1ab23cc24edf2e785f44045cfe74ab1e620ee517181985e7df0b0cf4437","0x8974ba3fc0a73a83995ab6d89c503551aa6db4a484dc3f33b4440814a8437303","0xbf2a78669a64db50bc28c4eff133f1db8f39b2323da6a131f2f60f11b327a1fa","0x9254dfec0cb28f103bfd4e25a2e3a06d10c36a64b153176234be1c48a0566455","0x9d3cc06c3937557f1862da9bdb299ebf9ee986a51c41dcd1f2e91077652ced8d","0x8c0286446c1369243d80955c97cef98aa0fd7b09778754a868f9cdd69354c8e8","0xbce07e6be2cee6635686b593b675c4084905e94da4cbafa80751a2ba9e5b5298","0x3d4f7a685caa6c40eabd5de4c69fac73152a08a2ae7e72b307d4da0cf4ade826","0xa76719a78e8e579e559487f33b9d9fc6065040d3931f2a0b3c9f2dade92b726a","0xd17de09787ddbfef94b572eb75ef1ae424718b172c1338fd7cfdd3a051cc3d6b","0x185579849c0e9aa1a606a1850fd5def91a1db337599665c55e5566999ae1e55c","0x63839bb45cac37adfc9b11e8de508fa61a384b43a0ad0eb2850c2f887a7f8c32","0x6702af2278fbd02cf8e68636966ec6c267f7aa6c53a7000bd79b2da5b4ac560c","0x1eab76961ff3de036a7bf2adfce9fb3b5739deb1cec6cac23abb34fdde9d7e6e","0xa39702e7d3c454477a7cb9e2615bf0865ebf55fbad0f6c8aa7f9d8971aa19ea4","0xed85da690220ab91baf719d3439d22171c8f321dc59b8ad6fe0db6e4b2dc2458","0x98d661b2acb7f313dce9eec7e3c48f5b1916349c67514795a207e856eb9e4b18","0x5794e67ce85b69607ffb433aa456361e14c0afba4f8ec092d9ce9831b5ee6d09","0xe7a7a75729f5da0367d1c79bebef6fc74aa8886fc4452b74db9dea8e9bc30dac","0xfddebfc8cb89be4e3f512b58a6876b083ccdea67f3046575a5689ac831865b0a","0x5773f1767a1e784ff5044371688f4c1949b5e6b52a4726cb9df835e0406eeb77","0x0f3a4cf051991138b63fdbea1ec8b3780bd947713a74c3bd628e5dd80f5a3541","0x6a6025260656819583468d3f730b6bb5528d20f4b8c80927fd3420fb8fbf0238","0x2f58136498d025f0bb30c8c55cf3781b3b1f8fe5e4080e14ede510c2cbe62c64","0x87c0a3fb37c01c1b4fb127e383576b4d68a2783b89335e0ad0e10a13e48f98eb","0x98125dbcec412b79c6921cd0c39e05dea43413d4cec210edb47ff1c9ea9401f2","0xd7ad404e65f321493ca93f6f0d2853a1660e95f9de50797d7808a9bb9e00e21c","0xcf96afb107414e1b0b383dff311ba84820960eed6130c0a2200662580dd5a23c","0x5f9bcc1536467d55d5531548038654d7c2b8579e8c943199e3eddd25f1d20bc2","0x39811f217af638d169d234cc885e2bf7edfb760f307249d9403744eb4c5831e5","0x5276c6262673d42e9cfe03b3cb3dab63d2ce8ae1766450d605b27b52cd65151e","0x871369e3251a8674011081fd9f755c5cfff728306969dfdb6ec13b8187978f97","0x393af11b8d59b268f62794a960f4e239b4a7951e48c48b35126853274b4c1a46","0x98236a771602526744244af20d314450b28af4daf2a8c3b03f1b03f0f63b8abf","0xc90e59530b4e7dfebc8f4a42c21d7e152d02fd9a65744b40d2853cb13e9abe23","0x2ac5c70b5ec5dbba4c7c901588abecf1e95458a79cecf4be62cc36633416e587","0x70b0f21db96de2bd91e39457039f4f559443b065668bc6f74796933e5b4cc30c","0x209a76661edfbeb765c0b7e35c7f6666824a109fa33f67161f9a98f0e87272b2","0xf319ebc84419b000d681e28a5c7f012a1c2ee5d8d30ff45d75ff84218e3ed9e2","0x5c7bf3c7f584ffa5d2cca52845c4e5483b20658bcc0d6b1b521cbdec991997e9","0x361b39f1fdf3f9182c4a18dda7fcb1ea0a4cce58fb0a8660477135b349f3d0d7","0xac9ea903beee814ea08674cfdbf38c75bc37fab7337a038c8074910cf8a94cdd","0x7552c996caf8c85dad7965d2e18af8bca864d1da825beedded82598e83764015","0x0d61ff46ca7b4f9906e9cbe2f243f90104a59b02c3cd65952bd4304f7818e583","0x4f1206e739bd6d05c59ce4b737190f6662c340aec4c09b044eb0bd88cb9e1b51","0x272f26686029a4c62ea77e26368cfd4fe4d577b5d1f1fd5dbc28658f001976a9","0x1843aa9a44d2c10bbc3ecfa1b7bdcd64bb129ff0156cc0e43ee2c12cdc6e17fa","0xe8eee24a23fe65ee522a438b413c7b232f00c9791a028e41c9e69032996e2b6d","0x3b1fb9eee4fc1e14f77d603b7a8e59fb2d897ad5f3b8dc00dbc16efd19134dfc","0x38e82ef20f33aae1cd4194d5f81d5dbb57da1e854b09f3e176ae4c18411a0b5d","0x27f5feebfd05597181c1dd7aa9d7db3ff9a05abc730f823cb4f7ff987241ce37","0x68ed81267e5d0bc1b6f21f0fddf41d9d1aa20af4459efe88422388d4d240ec5c","0x7330664cfb4298a67daadd625bc00cb986ad7176e71018d47fea02f2dd0b5e8c","0x3dc320bb0598d11ba1aeffab63a8ffd5c440dda87a3e8e97d8a108140e5769c1","0x5ddf110acc7e89012cb4755ecd713c08ef3dd6dd3ac3b18e545025e08e5b403a","0x1f1a74fa2d109221046381e90badc1362d2eb03c56f60e91e9ce56e5cd22880b","0x1f8e8aed671881629b96538129e342ec5b4ac2c7b34f3da7865bcbc15aa81a08","0x73cd6f3588ba69e9231204102353accf5bc5db61688a14fc243ec3e5202ce0cf","0x281ff56f2a28b5e700239cff48d55a813c0edc3e7b0eaa4a89e8f4970ee507dc","0x290027b3e107f5254fc24647d6ef4199794c3ee20649fd07b57cf1218a57fc79","0xb793e0cdb4a3577615c2e4593b657f4efe6a6b5ab8d204c89aabca1333568876","0x06c40de1fef805eacf69b7b754ec29cdd2fa1eb4b386c8e17aa61bf39ccb6b44","0xd314921c6ec1abd55a67b908be5a11054ef02d034a681b6903643523e915a14b","0x7e50f188e35298b7f0354214ac81b4e90c9cdbac084771d347d7509c1c64d790","0x731319bfe45085a828ef6b2b90ec630d4811dc77506c49a565c099bd9879f8e7","0xe692ea7f70973c8b07c366cf9bb41d178c0fdb835f03c0a547b56a08283730df","0xa844da8d5cc5ea85c23bcf734a108aa45a26f4fa6e8f62a57fbd5d4a57d16f8d","0x060591ed329c24701a72ee30ecd5a0b940963cb5ead67419ba96d6efca477cf1","0xc02e1c0f93d2eca21ebae97e46f09358cb182084c89e42a40976c760aca9d5c0","0x87ce974858174b6eb36bc2d759a16ecc5cdbc04d06e0b194c987d3f409be3498","0x80b5258fe8b6f17a1ba06f321830e6ca39fd24fdebb2f9fbae80238907fbfae4","0xad871e5e3b636595212e33a2d362c0a80527b2f42edbd413b3089535d03a6214","0x07ca82a3b8fdc99d3d90b9da307b75681f5e2e7b959237d34f9bfa99a9136dc5","0x2dfcf0b047d7efbd7605fddd346ec7134307bedd1ae3c3972d26b11129c7ae7e","0x9dacb062326e039741611899cf1007dcc7070942dae2e149dcf5009bba4274a8","0x7df955bb17e1c940ff70a749a359d3b7a4928c7c73f27897c09b007b219acc75","0x68c941f5e25fc9e1ed831911a363e1be490b55d1a95df9e3089f154f4a1294b0","0xad4310a56f5eb205e35f486077709fd0d272a901aef6e422445c4eb75631c967","0xd55321343fd11311c83b850a104e01e58f954c7d40c40e8901718aee2ff79c88","0xc09df8206a9903aaf05f4284f94645a1a868429d7e2f33159c5ec78982dc3adc","0xf3761e48323dd0008ecbfb9ad25b6a483e027fd4326c4ee7f91426c06fa76fc7","0x1a4efeb2d2cd49a02dbd3219c862c23cf200a1d954e853020866de8d1a0f2226","0x39686218060f674bb41e2da125e6672a751e1d3408586d87cc468e8dbdee3ee8","0x1ccbe1dfb4fd31d3ddb29cac21b81a682e1204f1be9a3f83e59b6e91960d1515","0x8ff1b00625c92c8cebd4e1c2d6beb177586ffa2b83e139539ac2a628b8a2a6c9","0x151b8a2b1e6ebdbbf487cbccffed1785cbae79b7a0542cb18d9ec1e3b6ed08e6","0x51f64b838e49c727412ec5c6244098645fbb56496ec70d8a09e92471dfadb4c1","0x00fbbc00a4ef17152a89e2b643bbfe0cf53622de971d0d02b49fbc8a67e9f24a","0xa0b4105eb08064ec73c13dfa3b952768bbc089d04ac8b15a9a5fa2ee28c0024e"],"transactionsRoot":"0x62e37a3921b729a7fc5e8be3fa685cb9dd88032a370fed049b8543f264a9eb52","uncles":[]},"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","block":9937218,"r":"0x12309ced6626c28ef82b6e086fae69233f11a59988b6381484ae4217f16ab556","s":"0x64ccfd04e01e3446112857737c2964c973654eebd9f66f5dd7b92863594e3fd5","v":27,"msgHash":"0x684999d8bb002f0547d945c96127656b9a1a9ad9ae843216ceb67c87604749f3"},{"blockHash":"0x65320852091d5af826648749e0c20f8e08f3a644a640e8841d65263ce249de99","block":9937218,"r":"0xf921ed047e75ab56b94fb44da0ca286cdb9991000ef274ace5dafe1a096eba5e","s":"0x11af667e6e43acf8aa80643d482e8fe91964ca7949dd6fe86f6a6fde0b363561","v":27,"msgHash":"0x684999d8bb002f0547d945c96127656b9a1a9ad9ae843216ceb67c87604749f3"}],"transactions":["0xf8ad830ac2cd850bdfd63e00830222e094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000075c2f1abc8883259b328d4f55bdef1dedde0bc170000000000000000000000000000000000000000000000000000000007fcad8026a01230f508c74dd0f6779cc8ee8dd17e3c4b317c975645311860df13eb7c40857ba0229ba3b4d88812a99b272e59283ec53923ffe01082481140e8b23405f36ab801","0xf86e821e58850bdfd63e0083015f9094abf9858fa187e37597165e1476e267be3c09f7c187e6ed27d66680008025a0fa4876c4bb5fa73150433b3a8e9198e4ec177db8497e927320747964cd7547b3a006ee804b91eaec495ed4f75f44f3451b67cc09669e9f396d04c2372f3d8f4cad","0xf8ac8308fc6c8507ea8ed40082fde89468e54af74b22acaccffa04ccaad13be16ed14eac80b844a9059cbb0000000000000000000000009f713d7f8a0c6f1a3b0bb8ead092d5c0c4527fdb00000000000000000000000000000000000000000000000000000007558bdb001ca07ea59a3a0a1e8388bf868bd02b7c0cda599e9ae6d78a8c3f1dfa93e3af7473b8a00b45ffb1b4f6c2bfed8249a8810eb9640af878c77eb8fcd1f82fbc56d4af8e95","0xf8ac8308fc6d8507ea8ed40082fde89468e54af74b22acaccffa04ccaad13be16ed14eac80b844a9059cbb000000000000000000000000d2a9f1132d24c3f0d806e6b1226bd19d34f87f18000000000000000000000000000000000000000000000000000000048a4a63001ba0b49b5847ca99a31527dcfc6fcb8a3f16665eae1f0cf9889f04aa927fe02b4234a0558ffc47fb951f92fc4b13528a886e562a8bb7a8a36bf41578a3f25cffc70fa5","0xf8ad833fa54e8507ea8ed40083032918940000000000085d4780b73119b644ae5ecd22b37680b844a9059cbb000000000000000000000000ac2fd5f56b86b0a12fcdecff9290be05ddab13e3000000000000000000000000000000000000000000000001a83e75087fb1000025a007aba932e0bfa3d539c75e988abe7ae476db32e9b9a90c155013b60b04c31f46a03aa4723d52519866cc79760c58c566842f7093ed916f083bcf2d388c7607331d","0xf8ad833fa54f8507ea8ed4008303291894a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb000000000000000000000000172e5d791e919419eb7c0c56d941730cdeb082ce000000000000000000000000000000000000000000000000000000002459aa4425a0ab6345220662ecf1a4d763586d21579925f9dfb5ac9286d72238a5092026ad7ea02f97866c9ae4de9733575fb63bdb1e4255464ec6856833cd34c4fa46e341b969","0xf8ad833fa5508507ea8ed4008303291894514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000251e93d51c5f2a1e60b7bc90bc8b2534b68e8f4000000000000000000000000000000000000000000000002b24b50e12e67e700025a0820374338beb3d537c09ab769097df76982cc10483318013bd3097a99062570fa07a75e917484950145e4dd54f26508debd9969c404937a54089771a8b3ecf6ed6","0xf8ad833fa5518507ea8ed40083032918943597bfd533a99c9aa083587b074434e61eb0a25880b844a9059cbb000000000000000000000000f2fb5a2a92b263fda28079f8318dc1768990b9fb0000000000000000000000000000000000000000000000000000239f235bf00025a040c609ca8a16a90850fcbe81f3f2f49c0608ee5bb58342391179c8e46e07794ba03c0d693d1fdf675adf6bf9ecbeac97f081217937e9e8911d05b3b87052a7055c","0xf870833fa5528507ea8ed400825208943e989027c6034171fdb912d81b70fcc46eb6d1e089042abe713dbdf380008026a0d5dde1918f6aa023ddb42d454786d027ad7eaf4d8877d92e4d1c2cde55dad969a002c276996f7d3da378b42a9cda02dbb04f90b16bc9f3bfe9e444a04fdc024777","0xf86f833fa5538507ea8ed400825208941bd4aea585ca71c00c5a694ab8a71e968dd7ed39880c934e1480ded0008025a010ae482060d67954f7bdb3fd95586ffd6bf440646ac0833c071f7cbbb47a4329a0344769fa8e21855323cd1f02d1dc456a6317e150f24384960b8a2b68ca6325a5","0xf8ad833fa5548507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000053b7de95320b8474e4a96302a8d70567870892500000000000000000000000000000000000000000000000000000000287ba543026a0afe104465085d312103810bb6fb2e89666184e136f95005ec97ac83d90152077a02f6d08f729e7adcd4e2240a29bb995a7238e62e35bb8f3f7c3984e01808da5de","0xf86f833fa5558507ea8ed4008252089401190eb8ff6507f85dd27c2726d59a617ac0a81a8804fefa17b72400008026a099064bcc0ee6732f8aa44ed4666d84ede1b27fe7b573c6a0ae6288e023cfc835a0269d9d191054698f1528aaf3eb2066ef63e87ebc1afec66b046735382b249d37","0xf8ad833fa5568507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000f578cca76375a83c7bf70d536f859adeccc50538000000000000000000000000000000000000000000000000000000001dbf343026a08fc5d98f7dd7a6ba256ea2350f8dafe4793e943dc6e3d06d5307c56a76796a5aa00a55b52a421fc140710417473cd47955a4d093a6167e688a1c4deccc091aec3b","0xf86f833fa5578507ea8ed40082520894f7757e7783eab1a5d26a4522f2dc0ec7579b57708803bf3b91c95b00008026a087fbb7a6d31144b863e79f0fca070d61fd355bd00b42cb7852c9019539a3fd9ca038b761f4d50f4bbed4f0dc2e72299053f23a203de26808704037e335c1203fdc","0xf8ad833fa5588507ea8ed4008303291894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000015b9d1f20a3a57ec9d3f55ceaf5cc66f417fa34100000000000000000000000000000000000000000000000000000000059889e125a0559456cb166cd667f479c1d0d4f10f9c5c0ba209f21cb2786b3d5746ce8d4463a05464cb35fa51cbf3d249b1f19a3779072ba22f5b926f2a13e85810e05cc7123d","0xf870833fa5598507ea8ed4008252089488b6cace7c485db4a33f4da78d10abce5820467f8907c341f0cf4d9c80008025a09b07a68a5f1d464935c9c7333c7955912f8bcaad1fe31b40411492f34eaa89e8a070af6a01b18ae4ebd59b4b4e84179c091fc008468d6f6e768f3b9c54600afe25","0xf86f833fa55a8507ea8ed4008252089400003605d910ecb5e30ec854b1e366562b1a12808886e266f566ff9c008026a0dc66234db06f40f9f7aae6608a60178182d07404913d8d3533396f5c7b2caeb3a044a8abc35cb47852ba5dcf2b9fe45ecec9cfd20e4ecbc49f450daf7a5857b283","0xf86c81988506fc23ac0082520894b0ebe65d836a6591aaecaa7471fcccef68f8c59b870e35fa931a00008026a07efae8330e4f6e1641e5d548bc6758e6d349d7ccfea24f57b682084daa9224a7a0665a84915dd4538dd95e0ca07d6a194d8037d687da2c67f24ef065657ada8b42","0xf8ad830c2dd58506fc23ac008301388094d7cc16500d0b0ac3d0ba156a584865a43b0b005080b844a9059cbb00000000000000000000000071254339e7e73c5ff115c328bcc54fe44b5f12310000000000000000000000000000000000000000000000000000000247f25b4026a0e3b54e33a5e739941551a217caa4b891ff54ec0a8eb2e37a596d5c07f069cb23a03abab2a09b32103cd70aca3cfe7cb723aadd71418893216cdf31782adf6f3e6c","0xf86f8221ff85051f4d5c00830186a0942c5ccf1ac4407e2e0e792f71f84f65d4679af2bc8843f8e8abf43b68008026a079b1336fd77e23cdaa1504e1e460714fdec5b3475c1895f57be92be06433316ea031f3cf4a2cfef3fa42a681a563cb4605daed8e4e961999318ff58c012e3cb2bf","0xf8ad83880a4e85051f4d5c00830249f094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000c82a47850f144aad67a29eec2dcaef5b9ab54010000000000000000000000000000000000000000000000000000000002c14fe7c25a00f2982fcdc28216d287b29a934b01f5b7c8e9713020d7779cebc8b07a02a2876a05bfa3d719eb0454164e2587391da61e864a00e3d950033040f1d6f5ef536bea8","0xf86f83880a4f85051f4d5c00830249f094c8817abfefb074732bfa62af629e2ef2c701532187e7a7fe3c939c008026a097d924db9cc558b6aa9927eab013309be3003bb3bfaac1d1fde1fa4e21e509f6a015515ed84fd52b8635da97c9d9d5727a7beda7a5c544934a42a19a32b86cb6dc","0xf881808504a817c8008307a12094a22c1b5320108c19db53f58241fd64b10556229688011c37937e08000094bfa6883b31dba961c0db9fcadd45f2ad651b64c926a02aabee2de83b5f8183f0c32d9fecf55a4c09c796c6f9618b2dd2c7989048e185a077dd136fe2a5d79855008457e662ace43d05857628baf134c3a47c0b954cd189","0xf86f820f4b8504a817c80083011170946d8e7336a9d21a5341d0d56283c7db067e77505888016345785d8a0000801ca0f7b1e0ca0cb6d5d7d1dd32131cdd9174d3683265f2bc38883928d04dda429846a05d298828d3eca8db494bd13e2118b64537daf8404ada1434a9ba23904c9828b8","0xf87183069aea85037e11d60083015f90947930f4e4a31af453ec937f37f153420374325ccb89010e96cfb1f69100008025a0d71300f6491410ffdd586300430d89ff7a506efa2bd678ccccfc8109c9acabfba04d72aca1b1a1b539686ee5d565b3c128ae558f82096337001301672ade0be42a","0xf86f8305a0458502cb4178008301d4c0945837ba345a5dfe649644c6a182ab0638355b280c8705543df729c0008026a09e9f073c4a174a128b9cc3557ccdf6f636976c3ac3be157bc0c26847defa8283a04ee8dc7cd157a1ad9edc98df533b40202283cdba22aecf5534e0f91275f8bae1","0xf86f8305a0468502cb4178008301d4c094babe4b38aa7a75197c81fdda9764dac16e437c108705543df729c0008025a02e76dc375ab7c1cce96f81133f5554b29454a300a137ac4ea27f3f85c3a4c003a0114e7cf8598c56a0ed20726e58021e433fdf60fa4c02076abfa4b84b0b1681c0","0xf8ab8275a58502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000df68356feacd6f58977c024befdc6195529fe51d0000000000000000000000000000000000000000000000000000006b679f65001ba0c104c411f44083472d27f7261ff377155179f69d92f2b7fb2574d857d4c368f0a07e069057cb7d91654050fe2ad88cc766f6fc90f06e236336a9b950171bf4d889","0xf8aa8275a68502cb41780082932494e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000e45f62b381e003090d09aea6304cd47e89c265540000000000000000000000000000000000000000000000000000001592a797501ba0f2d02788455eadef53902b2634789e88b22ab8efecd82098eb0e59e55259086b9fdae707d2a573de8657df87c9c75fb05ddc67bd9d7af49ab5200fd0f2a46a48","0xf8ab8275a78502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb00000000000000000000000086f7e6342f54643e09d3373f04b59e798ade70a20000000000000000000000000000000000000000000000000000000be5cc1f001ba0fe971df6fb442a89936d5a691e9228c6aaca1c00be2a1d12163040b12e325ffca04e50ed690c10a9511c72f1110d9177fa992368070db71b8909d885c62f7df2e1","0xf8ab8275a88502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb000000000000000000000000c139ba9d0f27a7e34ecd400c835da1d7b2cc9764000000000000000000000000000000000000000000000000000000239396f8001ca03b89f36d8d3be1b8e6a3eafbad2b0a0313c6b4995b9731169d1b814287042bb8a03e47406e40d9de6a0cb9399f69860636913f92a5e9fc29c9097007affc72f294","0xf8ab8275a98502cb41780082cdb094e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb00000000000000000000000098cc7030836dbcf1c5e2d18031ab3a157533bffb000000000000000000000000000000000000000000000000000000171ebdc1001ca0a13878b452c7acd8c46ecdc4feb775772931ce47e907b618cd6b989111dfb16fa0088b749ca3bc6851df557aabdaa72b0ede6de7d9b4ddf9ce2d5670ea17f5397b","0xf8ab8275aa8502cb41780082932494e71377e968354013f85c597f2ed888f33778cc6580b844a9059cbb0000000000000000000000005a42eb523ccd5ff58bfeb508373d6121ca59efd300000000000000000000000000000000000000000000000000000112cf5cbb001ba09290a91a776681c9fb9affbd1d81dd7261510fbdf0cf5ef43ad596df2414f76aa038fed5f344fc0100453aa8fa54de5e0b1a71b009bfa44509dc9c2f96dc9b37af","0xf9010c8209b68502cb4178008316e360940ba45a8b5d5575935b8158a88c631e9f9c95a2e580b8a468c180d50000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000007289e00000000000000000000000000000000000000000000000000000000000000010022a7c1100000025000033293b3c63730000000000000000000000000000000026a042ce3e6c352c27f9c01f474f8b3a68ea99091f738e48d6611c83d756d6546a37a0461240c4579d7d6749b88a64469c9a47bb4f8d48b787bc9dcf561d8dff16c4da","0xf8aa078502cb4178008301d4c094cadb96858fe496bb6309622f9023ba2defb5d54080b844a9059cbb0000000000000000000000008f20a07e0541ca2db9152d7e521aee5d639b211d000000000000000000000000000000000000000000000055e638836db86e000026a049c347e192b26eff3340d30f1e1e164cc83d724fa6c5c162509a166e6594850fa05e201f893c7a59122de4b703237fdb40ff66ad332ab84fcba48d1e74351ea6c5","0xf86e824f3a8502cb417800829c4094e80a115935c523799403573b6d5d3e114d5e03798806a94d74f43000008026a0155bee3e281a31b628bfdd0014ea660808597525a0282eb93bfd98ceded648f0a0250e69fa0845c5c291f7e2a744fefa8ac71cd172d6b4652f22e9d4b680cb8ade","0xf88b8242ab8502c667c8e58302e6309461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adbfafbc1ba0adba4cca4e9555eb8bede3d0433866376a98b223ab42293704e9e4c7d1c9a86ba00413d0e145379dab950d903b84859ba08c9a0f5b6db2680f3d5c08c7b7a463ae","0xf88b8242ac8502c667c8e58302e6309461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adbf66981ba0db8189f3aaef78fc825564d356c3dcc69544e3f7cd3fdb2e2ce4ee2bb757819da036079d587b2a5907791cd6d037e2fa2587ded9895fbf115a0b23c1ecfbdd9690","0xf86e82fac28502b82e9a7c825208946f964a58a2788c886356edfd632c2ad15efa7e35880f97f8a06f6b80008026a056bedf4f0f3434cfa758710ea95e25414dcdf08ae500501a9482835d13356569a0470d22308bdd8bc7b8dc537e540f475bd411e20a8fdd82e11f869adbf56c47f6","0xf86c808502b82e9a7c82520894777f415324d56e1d54fa832902d8797db7a4c57c88016f09e36125205f8025a067dc2fd858af1cc14d3bf251b3f48b3954fa518757505414d85b60623c77f400a07ba62f446c5201670425c8fdb2f3d8333e79b2daee5a88f1cf021622bd5f45dc","0xf86e8202098502b82e9a7c82520894777f415324d56e1d54fa832902d8797db7a4c57c8802c616739871c2408025a066008d58bba146bec9a7220dd0029bd086bdc8d6104b9b309dd2c729d40fbc09a01f94bf14e189810c47e819fbd1528c1a5ec62c7ff2b2fcb8a2796d47a484e61a","0xf901e48302b39e8502b82e9a7c830334508080b9018e6060604052341561000f57600080fd5b6101708061001e6000396000f3006060604052600436106100405763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166390b98a118114610045575b600080fd5b341561005057600080fd5b61007473ffffffffffffffffffffffffffffffffffffffff60043516602435610086565b60405190815260200160405180910390f35b600073521db06bf657ed1d6c98553a70319a8ddbac75a38373ffffffffffffffffffffffffffffffffffffffff811663a9059cbb83866040517c010000000000000000000000000000000000000000000000000000000063ffffffff851602815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b151561012557600080fd5b6102c65a03f1151561013657600080fd5b5060019796505050505050505600a165627a7a723058203f339a2d354208169adb91e00c0cc7ffc9a9f9e67930818df75c3724b686179d002926a061fb04c6a6df308fd675a1a74a6ee56fe97506d62c7e33821351e0807a600deaa05d92c07c402da3537221fef687442efd1027537d072bdfaf1ab867756dee648a","0xf8ac821ef685028fa6ae0083013880946b175474e89094c44da98b954eedeac495271d0f80b844a9059cbb000000000000000000000000d35631b88c6cd88383376978394232287e49fc110000000000000000000000000000000000000000000000138400eca364a0000025a0109922604a131435cbde54ff3a9a83aa8a9286921c58fa725faa755d09eebb1ba03e5ee58fbf1d9e0a76f650533ff6c9e669bbe2c0eeeb62ae372a18fb6c5d2d65","0xf902f482011585028fa6ae008302874a94241e82c79452f51fbfc89fac6d912e021db1a3b7876a94d74f430000b902848059cf3b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000006a94d74f430000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b80eb3c2b935b7a9ef1cef38979c3e44a9537e0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b80eb3c2b935b7a9ef1cef38979c3e44a9537e00000000000000000000000000000000000000000000000000006a94d74f43000026a04d55d4dd9278ef9b6a6d7b128c98a1e57370f1f4a67a0b5327bc652af1486e43a06ea212505cbae75ab5c417c680539c061e7a5ffff564e365fa06be4b7e2b5277","0xf8908085027ef638008303ecf194bcf935d206ca32929e1b887a07ed240f0d8ccd22876a94d74f430000a48853b53e000000000000000000000000000000000000000000000000000000000004a6db25a003ad72dc4435f2064ca3dcf6f45d504724796712e8776a5405827d93ffa6efb4a0256f09c0e6f30ac339813708a3870018b9a8b5ba5522389e3d6f563417c8bf9b","0xf8908085025a01c5008304252b94bcf935d206ca32929e1b887a07ed240f0d8ccd22876a94d74f430000a48853b53e00000000000000000000000000000000000000000000000000000000000481d526a059b23366736c70b076df6f9de10446824b8d9a5655c38625adfe0ba9f8c6ee86a017a610affdafa5908ac78fc430d0a53c5a25c368da69a349f061bf3cbfd49496","0xf870830103718502540be40083186a0094b80db769e504c71c5f327a508dbae4cac4610bef8828a417aaad2f43608025a04876a92b712091896596834d096796ff64b4c7fb54f36ac8674d3ea896d0c615a07a76509c1998e9d94ecb308c8b1f807914f7d3d3b9404a747b48f7ef64bce12f","0xf879808502540be4008301c90894a22c1b5320108c19db53f58241fd64b105562296809404c501c8a50b42f15d820994f472121b84b7db6725a0e306902746f2d1d353249be9b97fb054c80b52f1b4454b1a30af218ec4843485a01be8c134098de25d174abeaef7763ba757f92c635b5024c71e3251f89cdae59a","0xf8cd8301e1458502540be40083014c0894bb97e381f1d1e94ffa2a5844f6875e614698100980b86423b872dd000000000000000000000000f19df15dac2eb9f5c3bdddb76e8d562574e8f69e0000000000000000000000008cdfa93c08a5db9f62231b0310100dbddc73fe7500000000000000000000000000000000000000000000060ac8b93fff8981000026a06071087b45c8afed41ec3e87d4c893b61aa250d0fa982cc519c2ff6fc93562f3a00410d8a86002eb4fde74ccd4e04e15345a41c3ac7f651f2608703cfe4dadb479","0xf8b1108502540be40082deb9947bc6fd7c839c7f726c937b5bd185f19af8988e59881158e460913d0000b844f39b5b9b00000000000000000000000000000000000000000000000000000002a5c6adc6000000000000000000000000000000000000000000000000000000005ea3471e25a0242e34d752a694e6f27a56dd9fa96c370068b29d22a3bbde8a52495e24ad14f4a05021986e41c1101743abdb6141aa5ed722ef51e9014680855c3e193e9783bcb4","0xf8aa068502540be4008303d09094763fa6806e1acf68130d2d0f0df754c93cc546b280b844095ea7b30000000000000000000000002a0c0dbecc7e4d658f48e01e3fa353f44050c2080000000000000000000000000000000000000000000000878678326eac90000026a068ac5fe381fcb553f726613558b476a0867e8ca42de34a5cfee41b695675fc4fa005d662ec8314a69164bb5c70e3c6de812e9b7b93d9406846602c89fab974286a","0xf8aa078502540be4008303d090942a0c0dbecc7e4d658f48e01e3fa353f44050c20880b844338b5dea000000000000000000000000763fa6806e1acf68130d2d0f0df754c93cc546b20000000000000000000000000000000000000000000000878678326eac90000026a0df859b0dec23e71adf720e69bf35175b4fed198e96a2e143127caae6286da843a05db7e93b9b285920efd90017c8ea9b6cb852de37d8a8e920da305e65cc6552e3","0xf8cc824e668502540be40083022e9b947203841a3d0f4e9ce2ed0a043c3b03a7ec97276780b864f45346dc0000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef00000000000000000000000000000000000000000000008b58b231df925f0ac00000000000000000000000005842cb65a699b0ebcdf295fd41e87fb4026b63a825a019d4e0a4f44be1208309598d5630cb603590aa23cf3cd350709c7c3662b642bea0119689a0b277b62ed9b237abb43e81b27fa1b9607cb50183041e10bcdf50a1ec","0xf8ac8232d38502540be4008301388094504b60a4133699c7056b58d3fe11ea73865a2d6580b844a9059cbb000000000000000000000000ba360e709858cc6a000f55c11f1c3450c7539c400000000000000000000000000000000000000000000000000000008752be58a926a0ea02f18d30c97e88a503082e9be1805d206ec720687edbdd3b61097f7930b252a0515d99e0889a524b7ee62df86d6c94fc6b85acc92f17dbd1e7f5133d77c9a657","0xf8ab8201738502540be40082db9194dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000a9b1c1b6829c2150b4be3105ecb302fa357da2c50000000000000000000000000000000000000000000000000000000005defda026a004bd1f743067a7faa21d24b9618920667801a792cc13cf4aa43e18266de90010a059acc26a65395337391a040e704ca53fd24866548bc68682f18fb9aceaa84247","0xf8ad830133f28502540be4008301d4c094966daed1348fbd894bb6c404d9cddf78a993291380b844a9059cbb0000000000000000000000006975759cc901bc0f6582e2c75368501052948e2f0000000000000000000000000000000000000000000000000000000131c596801ba00220070294c79316c34c427936352c04befb4f07076ac01f0db15d46b27e1cdba05cf3974fed2aec3f1855c4a5bc224f34659cbc936108dc385ca34bdf9ce15d61","0xf8ac824b738502540be400830186a094a5c43fff568fc2115d54499d4cf202bb490ef15280b844a9059cbb0000000000000000000000004e5c838a5958e74cd30b23bd33437b3abe10f9f900000000000000000000000000000000000000000000000000000001296d5b8025a051ff4817793c33255f318d3c76d8e4aac47748de0ba414af26693f39f4b7cb3ea01ff44010406119c88b1f2ee6bc126b390ceb16712682b8f5839c12221c9f0314","0xf8ac824b748502540be400830186a094a5c43fff568fc2115d54499d4cf202bb490ef15280b844a9059cbb000000000000000000000000f80bd892164cf32b315088d14ea09bf0f6c5816600000000000000000000000000000000000000000000000000000001296d5b8025a0b3268bbb02ef0b93e1d09f47425ccbcff0b5df8627f31c0526505d6bf9f439eda0570fdd1fbdad146a1901af20b023f579f28b10fe7e5244cbe0eeff033b890e85","0xf8ad83013dce8502540be4008301388094504b60a4133699c7056b58d3fe11ea73865a2d6580b844a9059cbb0000000000000000000000000b36c927d8868ce6ac4e367bb63059111a5bfe3a0000000000000000000000000000000000000000000000000000000abefbcd8a26a06af3bb2cbd1ecead7374948a429ad1807a5750b98fedf58c2eb28378a4068834a041238d113cb6a191f2a4756c819e71355006b4fd3ca66699604fd4df5e4f63bc","0xf8f2820ca9850218711a0082fc7494283af0b28c62c092c9727f1ee09c02ca627eb7f5875ed8f5d8362c2db884acf1a84100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000001e18558000000000000000000000000000000000000000000000000000000000000000f627269746973682d61697277617973000000000000000000000000000000000026a0ed536b66b49d579a8f087c97dd475df277290d988b0a81a8f648c25452feb1e2a024487ae773c504a3a25d69095efb47beac80d55361ae09cbd04ee3bf1abe53f6","0xf8ac82093a850218711a00830aae6094f296ec1921acc61303dbbb88e5e9517a015c2d4280b844a34e7af200000000000000000000000000000000000000000000000000000000000012da6dd6ff73cb59ddc350c5eb8e63be488937e6cc82c0e1e71071670177791230951ba0bad12d5bde452d6426dbb0b20b6e727d7b73141f7192997ae1ca8233dd1b25ada05ea58260f9b3b7d83d59c545221541bea258ae127449752db1d73b16fa9bd253","0xf8ac8207c58502068f770083012b95942b591e99afe9f32eaa6214f7b7629768c40eeb3980b844a9059cbb00000000000000000000000037b1306594b1a098f693612adeb340d99bbff90200000000000000000000000000000000000000000000000000000b54cdd9c65d25a038ccb1fa13a7ad15809df184de5d7eda5e1e2f9ebc9add26dbe5e0ea5791e4eea03bc4d594bb229dd31b5c4cb566ee1713dd9c9a8eba32c713dfa0d1aa52711398","0xf8aa0e8501e2e61ccc8301d4c094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000013b6a458d375c4c0a6bb5213b82f547005186200000000000000000000000000000000000000000000000000000000001dcd650025a0f5cf471ac06b3eb0b3e644c082739410bbfb851b2803028a553949d9bac362cca0435a14db3382fa4d5f66c2427e66d117e9716ab9ae32dabdd124ce3270ead408","0xf90135827ed78501dcd65000830249f094d1ceeeeee83f8bcf3bedad437202b6154e9f54058902c40b73af386e0000b8c45e83b46300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000097a20977588f20eb27c742c91e24725fddda6a34b486761563470cc87c857512cf5813ba2330dee43fc7c23e766ed67429b0961d9e6b9df4ac0c5a67ca0116c9fd65ebd27adfbf6a69cf668d65e4bfb64d4f0032f5c4275d22f4d418e51109489603ff26a00ea72ac216095bce5224937a46f9ca3c952d3d0472270ca4e43b3179ff81852ca02f9fa732a679aeb3f4d5b7916c8ba5f540b707238219ecf12d66d15f4604998e","0xf86c808501bf08eb008252089482cbc94d37fe735e7240c2af8aaf1dd5c4de6d0c8804bd7dd09aa83450801ca0663103f0540300430018ca333ceab04a1c0080b1634c49347f11cd714ab3d302a034fca647a15f4b8339e20385030dcbb1f91e46a14b3a392901e1743fddffc9f8","0xf87083062bdd8501bf08eb008301891b94ed0fafe6846e281b248b1f67a90a3e2728875c018806f05b59d3b200008026a09cde8c745cd157eedf6d1c5dfabced125b5329d19dad7eea63260c5663e01576a016ab3deeed50455b749bbe297f02499819748c38c12a960a7c551444c8887a96","0xf86b5a8501bf08eb0082520894e48c9a989438606a79a7560cfba3d34bafbac38e87b58cb75fdf44008025a043d981767af343e943d2374651b3dd5e5ffd9fa171118025aa2e4e44663f0cc8a05eadfd85e6734f3d9f70334d6e4ef72a0fdb12f168368c6f009acd06c46345f1","0xf88c8302c6548501bf08eb00830147c29461935cbdd02287b511119ddb11aeb42f1593b7ef80a44f9559b100000000000000000000000000000000000000000000000000000171adc0858625a05195249fe90179ca869d279a548048e24b46c05c122b5e9d1b4a3723f6aa1c6da06d53b3b46b9f325285d85dc39598f5c9d9394a168f3eed2d3adb74dfab3156e2","0xf86e8213778501bb75640082520894ee329451cad5dd693369c6039d45e68bdd4476c888544cf590e01c40008025a0b6b4263519b70a09374befdf713d5b2bd16c0f25a0f3911c1962dfb43402b611a06e46c4dd901aa0dc49ec231bb619f386311bbd410df9f4f3a7ed4d493655ce34","0xf86c118501bb75640082520894835614a871942ae1a87517a7af2cae8a59e42cb88801b679f3a797214f8025a0ddfd7eaa32a33547b40c4d403b3b23122a6e788b4fd12ca20acdb7bcaaf06f90a0361b05834c02c61a534e5c911f1a63f93478a82c6b1c6a029aa8a278daaba917","0xf8ab8211c98501b9aba08082d2d294b149d8c556d888785ad13adb67ed29dc64edcd7180b84440c10f19000000000000000000000000c0232fbd7acee905517dc878fb50c6ae1629a4b300000000000000000000000000000000000000000000000000000000b2d05e0025a02d21d4830c35ba999f622445a40d9d34c8b6a9a33170d26934f6ddf130cbf849a05f079da12b6575de48db788beb36582088fdb77236b0e19b0ca4f5f1135f4492","0xf86b018501b9aba08082520894a200006fbe7718b32cc52fc3111185785614810d8804787a82a0fbcead8026a05f5a76f4caa2f46984d1d454611c0bb6fd571a9ca36cb482b6dfc6fcc0010b7f9f07c60c94ff795e737d25fb6f065dfeb122167e9c441cf22afff37e134a43d3","0xf8ac8220918501ad274800830186a09465c0469fa7a3ceb8130598e90f5f76c11b7e51aa80b844a9059cbb000000000000000000000000a525dea492d3e20598df120a115ee10d43ed613000000000000000000000000000000000000000000000000340aad21b3b7000001ca09e901141878c060c45e0f30c6e7aa862cc99f8989bbb79492c3342c406e92b16a039589efa0ffd423524f047e1056247382f7760bacee246e9febfde63c4341616","0xf86c028501ad2748008252089444284cf791085f6830c31497a0defd4dc83cca018807584246e3bb724c8025a02a9887396a13c3a280f5ef27c7ca738b90eaf0e184eff42cba66ffa913277296a04278e9fe2fa6443ddbd297f7688f26706847e409d54830fe5645763627b6d947","0xf86c2c8501a73167008252089425347464ef9f5a32ea511e6eb13bceb4cd9067cf880de0b6b3a76400008026a0a2a7074b151b53e8bc4d7c3358bc71efb3ef167ba4ce22aae60fb66538b043f7a02bf89d2c507d1f1ffce15dd9f58dd4a4421a414332b3b0d505c34f219a2a4874","0xf8ac831c718d8501a13b860082fde894d1ceeeeee83f8bcf3bedad437202b6154e9f540580b844ca722cdc7774dd0216e565cafdf10776bbee9439ffa75d2516a6138362ce0733f9e8272fcecddcdc0a45a9f143aa1c512e6b730d6747d8947f53d56df255c35f2504e0421ba0ddac112e61908846fa352f7fc0150460764845ae72a649391c5baa94f203f2bda04666ef6ecefc7a448e7b7d76a33f3d13106991d4537f2781f9e6da4cf42a9dc6","0xf86b808501a13b860082520894fe547350558ae6b7589d32ae46f088cd0298c86187287a4f4827d000801ca0fa53053c330ab79d150f5c3ceb025d1887fbaea74b8531f8ef085368fd84f996a07b7c766897be3d79d8078b96f3bc55e1521d0ac65a3dec7a88fcf9e98c8fbf91","0xf8aa81908501a13b8600829538947b0c06043468469967dba22d1af33d77d44056c880b844a9059cbb0000000000000000000000002722c37bd9886294a00c79bcafc5de66592ce36d000000000000000000000000000000000000000000000000000000000a4083001ca06b16b114de4dc52e4fef123d3563e8600dc5f47ef82ae583b9dee00d80bb1cf8a06287aa966567ba8df76eb15075a069b68e14abe6df40aa51ad79b72579392a63","0xf8a9028501a13b860082ac4a946b175474e89094c44da98b954eedeac495271d0f80b844095ea7b300000000000000000000000029fe7d60ddf151e5b52e5fab4f1325da6b2bd9580000000000000000000000000000000000000000000845951614014849ffffff26a09b2bbda2f38a52e55789d5a513b8336380c38b283a03be10f8d203360efaf98aa04323d37250d9d3509e89fab94837c92658542115d55a2d5774f1465accdc533a","0xf86c278501a13b8600830186a094f2dc0346d4b8bd1d7e8188207767504e0d10f65587b1a2bc2ec500008026a0052f03170155ffd35757191c543098b9ee6490a0765a60d43ff2b2ff3924a082a008a17747c14e10e69d73e75047b85541c4c589f44fc5c12484f508a2a0c19122","0xf87183092c998501a13b860083015f9094f4f28f4f29b3ba67e22f735103bac850e71d0656890277dfbbdbb224ec008025a0b7ccd3678582ec1e79a0a57dd030ed66bc5fb3ea47ecf2d171cb57fe2079d412a00e7f456c81862e90a3a0a44cbbe0722b424a39b547cfcd15db8dbdc5da342d43","0xf8a90f8501a13b860082d00f94a8258abc8f2811dd48eccd209db68f25e3e3466780b844a9059cbb000000000000000000000000df837c10b9f265218a117d3f490ddd2bc5574d9a000000000000000000000000000000000000000000000000000000174876e8001ba06254d55f64dd9fa3bc3061859440f09c800b3ad4a61e5f51574da8389b764d7da031dffa690d35694598d61b7ac414d25f192748be31e9359eff325448f918ed47","0xf870830200a58501a13b860083030d4094fbe5ac1817256b016ded3277d205ef99b39d771e88160d4314c41880008026a02c4ffb32f487e65f7c2359f1dbc5ef3342a37acd5111b038dd5eb89b27abd7ffa063fef3e59c45785dc586faff753aebedd57a7f9fb3ffd4f61bb2897725b610bb","0xf86b048501a13b860082520894fe547350558ae6b7589d32ae46f088cd0298c8618734b18b26e3fc00801ca02bc9a16a5170ddc2bd0614a1e810efbc09d2a091e718a36aeda35f0613966faca06ed035d9e47d0e8b57047759e9f339d5c7bc20aeeb7583e5aa59cc82e3cd71e3","0xf86b068501a13b860082520894e82215e4cfbb64e4fa2075fddd9d063b11462bea87bed3787bb4b0008026a04aae7c30eb120b676897336118d388dc193ff5f0e8a9f1133875daa6d7243a95a016d937b3d31cda049f3a3a1f42f460bea7ce63ed62f7a88b1fdf4bad77656b83","0xf9026c81e185019f75baff830aa51a940c651af07dd28b9f8b1fd283bc408d6d1ee214ab80b90204ed02dcea000000000000000000000000480b8d6b5c184c0e34ae66036cc5b4e0390eca8a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000914fc762ffcb63c5ddfb7d08d94df5e49ca984e9000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000221220b79e5dc3cccf37aa744c4c7529dee2d046236b4d671a1fb6713cd750dab4f36400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221220d4302c51c7ada234f2078c308ec546164289f820d7c63c427ccba8fc1d49386b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000221220d4302c51c7ada234f2078c308ec546164289f820d7c63c427ccba8fc1d49386b00000000000000000000000000000000000000000000000000000000000026a0c6c6be9fc7ae8f6b976f059943423d43225eabe4070e4e7439e6a9f54e3a639ea039b26e87bf60d86957ddca23cda2cbcbb43c99518b88191549672ebb73e0f95a","0xf8a98085019680f10082a0ed94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000025a70c820721673d9833e084fff64de0ad79fce00000000000000000000000000000000000000000000000000000000002625a0026a013ee28c24fc2742821284c446c51452a7ae92d3e11f7cc8852e273acad7d8fa6a0157261e7238b766725b417bd0d128fcc1cef4beebb74a9c8e5674e301e850253","0xf8ac8204f885019680f10083015f9094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000fb90501083a3b6af766c8da35d3dde01eb0d2a6800000000000000000000000000000000000000000000000000000003b83e6a0026a0eef4ba1bb14b58b1ea8ac74800b0eb382e6ccc52a3a77b3264b77a54b2077245a04e78349d900a3e4917618cfe156aff356a74ca7ed770db0d8ebbc887b494a90d","0xf86c048501954fc400826d6094f789a142e7f8dce675f0c1521a3ce3717bb56477880855e978f2a3d6008026a0b4b75f88cd3e75b4121f27909c97b42c707c90f2680c5d1afe68c244acabdea1a060d50c4c6269ced423ca9f54c02b50842bce5db38ea14ca199e2d961f48139dc","0xf8b22b8501908b100083039627945acc84a3e955bdd76467d3348077d003f00ffb9788058d15e176280000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000526a03df6511c1672630e669d9725c7cdfb7a30a34053ce5791c6566c86137083f342a0236be5cc9044c831c1419ac77cc843e223d8561ab3f7c066037badf68e2bfc18","0xf890808501908b1000830742a7945acc84a3e955bdd76467d3348077d003f00ffb9787b1a2bc2ec50000a4797eee24000000000000000000000000cd8aaf696376f2daa7a80cd2c91b32f8adbf699b25a0acd4f656e3a1f1dcdcc7826a42f13ae45efe8bea3e71cefc809de0949b934718a001c33054b0d44eab6a1bf1f5a2de24a42c2c406c04c1baf7768a1be97ec98ef0","0xf8b2088501908b10008303107e945acc84a3e955bdd76467d3348077d003f00ffb9788016345785d8a0000b844be389d570000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000325a03ddae2974b6a761f380cd575dc4b8ea00e9a012b0d419469466a1bc05c00f3b7a0331407619e31b7cba42ede47ae800999f5ed60486376ce9f58e29027fe9cb343","0xf88c8301029c850189640200830402c794794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000042b921ca023e4742a8abe8da3679681cf52f885f161cbb0aa6f2780097434553c764432d1a020f69a6f52da6c74b05c0f7fa2a685c62407d02c4ca7275fee3ecea2cb3b60f7","0xf88c8301029d850189640200830402c794794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000042fc71ca08db742a2ff6287462aa47b15576d419f1ad2d4f5eb857de77431f2f668c45b96a002a9e9835b9f5a68ea7e79dd82ece2af95fc859357154f47c67186a1091516e8","0xf9010d8301029e85018964020083057a8094794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d412000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef000000000000000000000000000000000000000000000197050486b93af200000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000000000043c101ba06535b003355a3f90295369c4a0dbf6f0a6f93404752104751e9fb17ad23d8149a024cd88be1aa7f7bf6d8093a2c2556da799c93a95ce31d6b60ce8b8916828b6f1","0xf9050d8206a285017e10d68083011686947be8076f4ea4a4ad08075c2508e481d6c946d12b80b904a4a8a41c700000000000000000000000007be8076f4ea4a4ad08075c2508e481d6c946d12b00000000000000000000000044e9d011df8741be2493e99297e9ad67bb1aa85b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b3256965e7c3cf26e11fcaf296dfc8807c0107300000000000000000000000079986af15539de2db9a5086382daeda917a9cf0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001158e460913d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea3425e000000000000000000000000000000000000000000000000000000005ea7373fd7e6cce81d49fae5ac7183929f9922d6299effd45ff0eabff485e447b4afbd250000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000001cabb5b92a6b1d485f4a95e1a9ae0dc3810b55df975cdffcd9a7298d18ed1076117bef55c7602a09449581049a66c6a7b8f9a86a9dd80a20cde8bd873e734d8a0a000000000000000000000000000000000000000000000000000000000000006423b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044e9d011df8741be2493e99297e9ad67bb1aa85b00000000000000000000000000000000000000000000000000000000000009a100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025a0b785c33350b6e1019ad23d9681df2e0397793c84dd398a273c9867b578e60628a062996538f80d74b38aeae40108423cfeb52a1dbac110637b95e4b1d6fe900301","0xf8a96185017e10d68082af3c9457f1887a8bf19b14fc0df6fd9b2acc9af147ea8580b844a22cb465000000000000000000000000e7076ad17313c843a1f8a03af86981496f3a5eb5000000000000000000000000000000000000000000000000000000000000000126a08b641488a3b3a3c25267af47edc277ee6dc5c3400b2a6f94362aaa3ec353293ca0074c1be9b4d57b4166582f8e0b530c4924bfa414904788663506027b0042a26e","0xf8b10685017e10d68083030f2b945acc84a3e955bdd76467d3348077d003f00ffb9787b1a2bc2ec50000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000225a074b03dab1ff6b220b92af9debab1b93efac9c92fa8c7c1f67fb943aa935bdff1a02bfd7ca8439316b7967970b72594c1a70ec27f7f6c763f8112e32b4ec52abe07","0xf8b10985017e10d680830c9ea8945acc84a3e955bdd76467d3348077d003f00ffb9788016345785d8a0000b844be389d570000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000325a06f8db8a1e385a1e8c79fc67b4ae9410eeea22f75b39e66e374e91ad32586bcdd9f819e942b068e205704a73ec909c11457bd33e175fb696f8a0b344e98d7df4e","0xf8ab818c850165a0c0d3830144ed9434848f3c3934733d3ebc6f82489346592566c77780b844715d0e3300000000000000000000000000000000000000000000000000000000000000150000000000000000000000003da1eaba88cc6199dba96ca5291bb9fe8058ed9a25a0a18849ccba323e3825407e702deff761ec83b2c58ea83b74ef93eb982a6db2bda01717a77314b5496a3fc81ef7612fa1ced8fef28a8cd7ec0c8b5b622f0924da7b","0xf8aa08850165a0c0d38301388094e62e6e6c3b808faad3a54b226379466544d76ea480b844a9059cbb000000000000000000000000e62e6e6c3b808faad3a54b226379466544d76ea400000000000000000000000000000000000000000000000000000000054cedd425a08024e80e6ed797e6225fbb4c3153be3b54aa79a44398c58c09fd9137aa3e203aa05943ec2ff98499d6b4ec533834f5ed467a836a30f5b57713db0346ac12bbc2de","0xf9036d821b96850165a0bc01830281f1946f400810b62df8e13fded51be75ff5393eaa841f80b9030465cc3e7800000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000050c1ee000000000000000000000000000000000000000000000000000000000050c1ee0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000050c1ee000000000000000000000000000000000000000000000000000000000050c1ee00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000077dc088000000000000000000000000000000000000000000000000093a3d4e254320000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000093a3d4e25432000000000000000000000000000000000000000000000000000000000000768f42d225a025edf12ee9914c9dd38043d40f523b9651e0870e936632f42821d3d5fa14fbd9a059c5a6cc135bdc74a31889fad24f9b1c146b692ec6a10b22b4ae0c8ae6210f36","0xf8aa80850165a0bc008301d4c094e99a894a69d7c2e3c92e61b64c505a6a57d2bc0780b844a9059cbb000000000000000000000000478439ce384d46acfb4376b4ef8152da9c3ec4b70000000000000000000000000000000000000000000019120301a452ada040001ba056a50236fed0c279ba190bb84bdeaa6ccaaf972186c302337c7d4ae3bdb8a040a056d61d7b9931aaf070edc9c79a3ab745203c6ca729eab4e3535d51a76efb2dc0","0xf86c5b850165a0bc00825208946ea9090eedce9673f09e1a1ecec5eee6efa5b4fb8824fa34a2040740008025a056ee4c813cab2dee483e3d01a4bac29586c8d465f3737701bdedca4f7a917809a0687b645ecf75cf2e3c5407d85a82a0aad2187be2e3d682fed0e189ec52a3e231","0xf86f8304645f850165a0bc00825208940226a0157035615044dcd69c5446cefdd40b61d28804082f089ca994008026a06155ed27626f61e387b77a2bf188efe93173bfd5df0fef7a700d9583108e8231a02efdc8081c75c1aa822794b0ab01efb97b20d732559fec6d300570893c722204","0xf8aa0d850165a0bc008301077a94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb00000000000000000000000017d19ae4a90418e8911c4d449abcb14df1f576880000000000000000000000000000000000000000000000000000000002faf08026a0c0052b8ca1e69b155a186251024e14fbde48025824fb0bf316b544e6356e1ecea00d529ad6501e9944f85697a62484799a32b7fb509f1e3549d2573248d4ef0a3a","0xf86e820e9b850165a0bc008252089475c652ad82d3b451975732cbee9442f0460e3ee0880ff78ca9a14d24008025a0e98f7f2302fc5f24ebf0fa9bac1f839667812a16e553cda8a138bd1b2d20edcda05cc893812a3826239c2c95aff610de684d120a10dd34fd6eff66e07ea72d78b9","0xf86e820e9c850165a0bc0082520894e7e256cc80ef44236d09fb330a41b9c8e138d73e880198c1490d6d7c008026a02fe950987fdff13b0e8e47ff538e47094af8cca9987a8fce851cc185d34495dca057d676db8066d39a7ed57c8fa3088fee4f8a3c2c9022eeca3437c54ca7c22463","0xf8a980850165a0bc0082bee7942b591e99afe9f32eaa6214f7b7629768c40eeb3980b844095ea7b300000000000000000000000005cde89ccfa0ada8c88d5a23caaa79ef129e7883ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25a0be539ac9157df94f9e2addb319f101f8230305bdfec7a5e725c7e5b1c408ecf2a051096c82fc0804ed55b79c534959a5289847b9d0803c80e8e897ef2941401797","0xf86b01850165a0bc0082520894722b72a2b63630a67ec9686134b226725c1b8051870912d722b5bc008026a04146991f11a34f94e369238e486d17ebc8f4c1f2394e597eb2e237d488d0d361a06c5fce15caa6d8cb2d23ebcd53163987049ee3d4e6995c976933edc068b96ef8","0xf8b202850165a0bc008301388094f506828b166de88ca2edb2a98d960abba0d2402a8810afbbb4a0f30400b844f39b5b9b0000000000000000000000000000000000000000000002752cbef197a961adec000000000000000000000000000000000000000000000000000000005ea3449f25a0b3300c5bb329cbbfa22a4a1a50817e1bcc798a02b87d4292f6a77071ab8a4901a0265e178a19322c6fb0ec6bd3fda1cd242ff3ec50e7ebff32aab0db5bfdcdafd7","0xf8ac82020b850165a0bc00830160f0948e870d67f660d95d5be530380d0ec0bd388289e180b844a9059cbb000000000000000000000000de0bab5882f9a559052b1de33c862baeda0abd4d0000000000000000000000000000000000000000000000000de0b6b3a76400001ba0de8d7933d60fb2d0d2eada3e9570a460b07c52d1d3bdcc2b18736f3e43af4637a0113daa377b705c888affb67da7fe9720132b903b5fb0cf2d3db92b8d2d226e82","0xf86c02850165a0bc0082520894a87939c16ec943352abb83bb91993651864f0d878801684ba67a0a84008025a0fc5d8db741f2c816cf0f56f7e4519e88f4a5144d46935d3d7a6bb6f737f0a911a07c9435d78b58feb629bd04ef0fcb44324fa7405d0dedff1b765e63a3f9e180a4","0xf8ac82a965850165a0bc00830186a094a5763bf433f2f154b798b924fb2f6c54137b352280b844a9059cbb0000000000000000000000004df0e87514027a97412e50901b58cc9c2c870f130000000000000000000000000000000000000000000000015cd58b3f7aef60001ca0cf384881d84ac25ddfc6ce380aa53e8e8ea6cda6a208a53d653361dd5c3542dda027f80df8ab3b47aa3a5e3582258942e5a26622e079a728975ebc7f63c88ddf5f","0xf86c80850165a0bc0082520894b7f09b6bb6856de1e0455594c02db9b82a4f2f0e8801121f313f9f90008026a08c556abbaaaf8526763ed6d752c605ac812a1e4ef2a76d4c3b48acacd610a1b2a0217d22fa812a71572612fc0ae7acc2f9b04f1b2e8123c034c1fee43fd37cf26f","0xf901b30a850165a0bc00830789b094818e6fecd516ecc3849daf6845e3ec868087b755880135cbf0206a0000b9014429589f61000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000135cbf0206a00000000000000000000000000008e870d67f660d95d5be530380d0ec0bd388289e10000000000000000000000004103a5bbfb7623d2dc63162c517f7d2e00d1d6208000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009d859ec812656cdde0000000000000000000000003ffff2f4f6c0831fac59534694acd14ac2ea501b000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000045045524d000000000000000000000000000000000000000000000000000000001ca092b70a75121767cc5e3e14045ae3293fa61a5e31368c988450262954f9b000cca01048e6ce0e68d0df9dc94f6577283657297b84a3ad83ea95a9fb531ea42e9966","0xf86e80850165a0bc0083015f9094232a66745d8ad6573b8df6276533d062651ee0e889056bc75e2d631000008025a0362e2b175947bcd9334cba590e7fc45b997ed844f53a91981672a6babc6f8ef7a018d8396f5f58c96c19e0f495c6081e52dd20f6180a2b46e8a62f1ddd65ef4a75","0xf86c0c850165a0bc0082520894053aac5ae100ef585ba179e4d043a1f7ebdd59a78817c51686734a00008025a095136456a9dd697f1ccec2fde5f6fe9a55804300d895612f3572115ec365032ca005bbbc1b635639ffe8fb34339f509a32f3fd3f7f215ce7dce3485fd84fcc1c60","0xf86c80850165a0bc0082520894ca268846f77ec39ec45598d036aa18d22786f9d388016e3628b89d2c008025a0afe7794441adfec77c8b40ec67b402d2515dda2c83b7ab558d361d58b9a113f3a0381da7ef505b524e53368dca662aee7cfe658e4e73ba2c415d6ba25014b4f127","0xf86c80850165a0bc00825208940145b171129d6c61e1fc6c1b5814078ad6c45ad388071023b317e704008026a0c31c53f3f8410f7ea5181950d2876c2534c81e01bc040b50d118ff6f9a293613a0094a1c627e762223f4a3468b1f05430430506d1e319eb90550f3b0258382d929","0xf86c03850165a0bc0082520894d8847841f90c35161ce838c685b2ead5c571cf858807628bb860f434008025a06b236042bc1ebda8717df8b7a2cd8d97842e7f0110b8b1584c95c0fe3abc9be2a02abf5f54620f68da7210e17761f21e0fd9515713bab617655489ea3ab3e6dafe","0xf8aa27850165a0bc008303d09094b97048628db6b661d4c2aa833e95dbe1a905b28080b844095ea7b30000000000000000000000002a0c0dbecc7e4d658f48e01e3fa353f44050c20800000000000000000000000000000000000000000000000148a9159f116abe9e26a0446e522ca86275dd742974ccbff97537487bdf7bc2bb898ba1a22a4279368032a0134ca9b5f2458197b0b15c3f58b5a8e404f6002877b9a71b41ea7f7ef295d894","0xf86d820504850165a0bc008252089482b398f92dd3851f31aca17a8a95fa4befca88fb871a6cd253d6e0008026a097c47654b19896ed062a99e8b7ccbf33443328b5b7a273a19d060090b945203ca03b2ce2e65c883f11293562ade777d9dc3e81f88b2ab80c86036e99c3b81b7e3b","0xf86c01850165a0bc0082520894a9e8e9ecacea1510d68595c595e1634f553c01d08807640000f23328008025a030a900bc4af976d95dac3dd8626069a29171751c36f4eb0a7f5c020ab74d07cba072fbcc5867d1b46b6930e59416e10480ef3aac234d4692cbb3116a33ed0d00d9","0xf86c80850165a0bc008252089457b4464eb4f91226ea02083f3de57acac6605d3e88067ae4ba417c90008025a0736d20cd1a6f09972ade785ed34cd8153e8ebe5e8b94a586a5ba795fb1291857a062ccf8c4d3bb190c61366af0bb57c906ff09fd8f8b6bad509889eb0d483fa5b1","0xf8ad830297d0850165a0bc00830f42409432a3256a4b15badd4a6e072a03d23404d925a5cf80b8442da0340900000000000000000000000070745fad98d470a9d2a530bf9323171b7f5b517d000000000000000000000000aaaebe6fe48e54f431b0c390cfaf0b017d09d42d1ba0722fadd61fb28375ccccc7f9b24ccfb5477cd6274ac9d5dbb66549303ecbe76da00e6709189b784347fd39cb4770c79b931dad97d68c3a32dc465fca2218fe8050","0xf901ee830297d1850165a0bc008302dd709475db8b92937f8f86213e523788ab9f066efde3fe80b9018439125215000000000000000000000000051325c06f96111298782a3929da28cb78b224260000000000000000000000000000000000000000000000000012be05524a6de400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005eac7e19000000000000000000000000000000000000000000000000000000000000a8310000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d0bcd35f7dc468ae0ba2a93773be02acd007ca8fc08b43c845afcb59857449111784756116466fca053caf3b61a97970268ffc5f8aed74f1c77629994aa86ae01c000000000000000000000000000000000000000000000000000000000000001ba0412d06e69db045642c0371139ab6362f3ac231300c328b7b94ccca35e736b76ba0331ee5bf31204407904bf9845ee150dc977c4f971611d9568706dcacdc3b9d82","0xf86c01850165a0bc008252089470333ce9c74fdece89196f6b2d5f8880dde1941a88dd89cdc99d24f8008026a00e4c9113298f23e720a502fb713fb7a58ba3599695e05dd488b410c61676f58da0594e2991a2c039c01a5e1d93bc68fd5ad9aaba2a9432f9655a5a90c50764e8c3","0xf8ac8258de850165a0bc008302710094aff84e86d72edb971341a6a66eb2da209446fa1480b844a9059cbb0000000000000000000000005a089ea0990cca43a1a74a4bd4f8a08473524c28000000000000000000000000000000000000000000000009d120eb8b477d000025a0e69eeb06fe2b7bc122b336334821449eba2d710c928f1efc4235700a2282619fa058838bb6651a8450dd9c5e4bdbc7e588cfb1b20f8c4ca1efb0769eec3f097e16","0xf86e819b850165a0bc0082520894036ab8ee93a36b229926e0993bba7452b00820f189083d6c7aab636000008025a0d2f33a740e59f76b5ea24388abfafc6fcb5a9292e8fd01ea6572eb222a17028ca0258e6379d14182519c3a607b458063ad005cbbbdc552c6edf18137458dd889f6","0xf86d8199850165a0bc008303d090941d6a916034d12065f3c669725549a6378cbc3a4e87b1a2bc2ec50000801ca07bddff7ec860ac26ac9d0d7fcf3beefcc80ef4c6e9e9df1b5011bc159dd9ad5ca04859bd62a67693c9e117683e493d8e726d01929f3ba336461bed589176c9e5fa","0xf86c808501620d3500825208941a5b5887f0d6fbb8804ef3fd7742b33805e791ba8803d08d97b5d7d8008026a018ad5685e8ff57d4c9ee4aac75cfb1472d7c63ecacb751ba3ea1f86219eb8c56a05d7666a0e10943a1ed958ff1f21825e031077613ac5e5eb738f9972bc4b67c88","0xf86c09850159b4fa0082830994aef93b6aecad4fe1d08c1712db3c4e8eb0e3a839881bc16d674ec800008026a00c597bb2fd1023d0fcabaeb414089a76ad8e94922cc7d7f3c6c8ca3041cfd9aaa00f01855c73075f8e3f61437d250baac62021356a958a9b997a73a3373c83d03d","0xf88b8297aa850154f046008303c58c94794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c80000000000000000000000000000000000000000000000000000000000043c541ba0b0b58afa6fb18f92ae871469696a2508ace166df657de718bbafa311196d3deca057cf7ede7f1c37156abf743cd5d95b845fab1d2653870e31147ca9e7f9366346","0xf88b8297ab850154f046008303a63494794e6e91555438afc3ccf1c5076a74f42133d08d80a4b4f9b6c800000000000000000000000000000000000000000000000000000000000434b71ca03df496e97fcdfdd70027de00b26d6dc5ce3b145a573beffe2ca8615c1c1b6597a073fc2cb6d6b1ebb0c28314087966cadcba2b3fd614d6c84b5ea7a05e445722bb","0xf9010b8297ac850154f046008305442294794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d41200000000000000000000000000000000000000000000002086ac3510526000000000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef000000000000000000000000000000000000000000000000088d3656d1eac858000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000043c3d1ca0733745a44f38d529e17ddc022bab257b9c1f3087fcb222c7a0094bf39f53cc299fc7c604d99ec80d04055e4084b7c5aa46119a53959742fdb75a030d490a1b7d","0xf9010c8297ad850154f046008305295094794e6e91555438afc3ccf1c5076a74f42133d08d80b8a41b33d41200000000000000000000000000000000000000000000000006e32adc59da7620000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000001ea0e23cc3bc3c4fcd0000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef00000000000000000000000000000000000000000000000000000000000000001ca07ec14919c68125fcf2b22e4bfb62db1361e0d3ce7d6825013f9d974beeb8c5e1a0161fa80341a09817ded4f3dc9ecb370287fd7e4de1b522242bb451cdcccd8313","0xf86c8085014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68811e569751b3408008025a022d0052ffea3111391a63357b454a8da67cd3c0c2263a2e6ced3d16d288c0b49a04f48141f57b157bcb5effd57074f84da13c8454063dc7c9a43e3c6331f74f095","0xf86c0785014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae688a48ec234949560008026a0218726a9be6b0813d40fb59a2b64ff9abcf7b5f6c892ea738282eef69f59d57ba0050f6320067f2d0a292b8f87b7afc4ab447487371d9782ef1f8eace8a63f179d","0xf86c0385014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6883e72cb9558fba8008026a0527c7f45db3f884b31bf8480dc75de6526530b1773811c457bca037eac256074a05691bec7343da7b3c696b868882810344d41a4a3a3e0d8e33385b4499dd2430d","0xf8ab81c885014c980b00830186a094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb000000000000000000000000e3d356f09f44a395007b1d9b13acb35c010ae436000000000000000000000000000000000000000000000000000000000007d95b26a078d943948e46b61e28ca6e393b2a0da897fd8b49705e6bc210d8c1d3652143caa005d9c04385ea5bcc772e121e840019733dec3459c27e59ff032fe14936ec5a87","0xf8ab81c985014c980b00830186a094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000e3d356f09f44a395007b1d9b13acb35c010ae43600000000000000000000000000000000000000000000000000000000000c139126a0fe05ddd0359a69c03abe61e9e5d5cb31d2c6d25521a11cd8cf8dbdf3bdaefb33a0635574c3024e017bfd90f4dedf358d81edec0964faf2f2d5c7e7ab9b822de819","0xf86c7785014c980b00825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6884e8baadc540068008025a0889d2d18cd48a46cfc07ffdaff7e9fa9be7d5fc38645c2ce9d987874bfc6e514a00c20c62856948431c076b899e37f4154ce0616aeb9528269d3bfd3bf23d476a2","0xf86b0785014c980b008252089425ea4690e4039e162c9a3acf002e4d984ea45106874b4f5eed7f4ffb8026a085740ecb2eb6ed57245b67e7d79bb14623adcf40050d684530f979d8931e6c07a011b07ff9747aa2a161a08651fabc5e7f0795b4e0496394b96f8b2fb475b63483","0xf8b4820a998501473f9e2383013880942e642b8d59b45a1d8c5aef716a84ff44ea66591488034d8b1a4b53f9f8b8446b1d4db700000000000000000000000000000000000000000000000da933d8d8c6700000000000000000000000000000000000000000000000000000000000005ea3440725a0ed4b6a4b2a52ebc91ca3cc43da62da33fb09d0b27aba2c60dc40ff1be0d26081a0631627863c10073cd9240746d35da164ce00323a188390825b55373bd0093e36","0xf86c13850141eebddd8252089487e90af244cc01bdc9aeb76e3c35e81255470c198807622c11947680008026a0d89193bff77e8117c089ce46dfaf83d9433c98a2f180b51c97d5f6afed56e88da0125a28c858716e22eb2ac08bf4d398ead0fbd05525d8b05611aba80282945c1f","0xf86a01850141eebddd82a4109400f0486a7d3d3cf0aa08b04f36b84ccb7fd575568616e041ee4e30801ca08d1e2fdaa6942e4ddb3cff6f9305f3210c5ce470bbc1baeaee0f9b75624c59e3a060ec0e4918b625557a4a0feb9ba120dd82f1b963dc1811bfcf834d2df02259ad","0xf8ad831b0e8d850138eca48083030d4094ba50933c268f567bdc86e1ac131be072c6b0b71a80b844a9059cbb0000000000000000000000001ea0c8afbae8126eab39cd7885fb30492cf430d30000000000000000000000000000000000000000000002a9a34dcc17c1b8000026a0edcad88590bd9495443497042957277d748189a205bedfeec663144cab438e35a002004f90f0f1ac9186001e5a69ab9aef27321a2f05955efe618860d49a483e72","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880de05500fc72e8008025a0d11944ef64d4d999aaff9d6442eb15b3956bf1abb1da0d7002de95de7019dbeea04d5ed56af376abad8f571208f26cddc9024b74cead49f2e93d6b589181380c8a","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880b207eb07426ec008025a05aef45bc4cf9c1065226880ea7518d7cfb6c56980de672554d3964ecd4a13281a0634e948d235364ca0d8bd8c471165a0c2538523039a699501078ff36d3cbdc47","0xf9022d8298e0850130e0b4c0830122fe94ced13f21d59d6caec0d4d0a31fd6ecc67a20317880b901c43249d335000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4538374230363438353034303130300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004375714f414e734d61484375436f7a39717a65354252616f744372452b7048544f3138734f494e70616a56383d3a6734705a6b49726e466f384e4664494a4f6c3232316e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000494b594f325a592b5a3374662b7a4e315868792f464b6b7a78316648513339752f4f74386f557149787148593d3a41447772657367696235345a36324e2f72775753306f403333393333000000000000000000000000000000000000000000000025a05d8006c088ba727a22414a1112b832a02aa3882367bd6454dba0910119892cc8a00de29d331ca890e835cfe4d8a8b88b347dc8c4a5d7894e29f75d6b6c738a12a3","0xf8ac828688850130e0b4c083018cc294dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000003fbfc3d00fb29bc0bedd30873924810e4bfddfc400000000000000000000000000000000000000000000000000000000016e36001ca0f8c3757396d94623bc4ef9e42db00311f110749363a68f62903ab0300ea88676a0289acd20d2f536651276845ab292bb0e6a3c7fac62dd4b515dbb96af73d7a29e","0xf86c02850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68806ed55ae1c9218008026a0f194e7e78f71d2a1a838dc0eb98fe85fc939a95797c39f4fd65543ea468ee155a065c12a094117ee97ee76aa946057457fe0ac23d6581bd90f7652b5ebabebb15a","0xf86b65850130e0b4c082520894cdbc6acacc658b45bc39a23c6676b23fd67b3167872eb2c0da9edf008026a014ae2955ecf7732f3316625f9991ee2fd6660263dd46eed28375f4a5aa43bcdca047179007de6108d91b6c7d4812f2224e546e4e353dfd296d2c53c255812c60a8","0xf8d4821c6b850130e0b4c083030d40942e642b8d59b45a1d8c5aef716a84ff44ea6659148829a2241af62c0000b864ad65d76d0000000000000000000000000000000000000000000000a8eabfc78526fa9d00000000000000000000000000000000000000000000000000000000005ea343cc00000000000000000000000034ebb9092b9fc46c7c0b285ec89b9811e8d6a1f125a0fc6607ed07f2fb1f5d8c97a83706eb799d9cd60691e934b43aa42a382d0e0db0a03a1fa62bb444411bce8bda2a65361a1e5a3984d2f3f7f1970e95db709b65ada4","0xf86c0e850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68809fd927cc356e8008025a003226094484bd711bf77d97f9da09fa4043005f68a5b56979ec1927b8e0c0988a040da68c0a7affca5fa55b8b36c1c11fc8c85d9e87cb01d9e9c4933a4097af2d3","0xf86c01850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae688070dc0231ca99c008026a09a53d068df20921dd40a14c984883203270894b266d25b637d74b468147b0f0aa00b67da286bc53f0744a85419d1bf828cdffd80eeb5e4d49d38e5739f87e9eebf","0xf86c0b850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880c7d0f889ee8e8008025a01f6c4a5f495222ec0927abe0b001fbc056ae4111751aafb5d6378b9c850d1500a05541dde05029375027f54d026fc74e48ca7a6e986c495d9bd1cb758681a3648f","0xf86c08850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880b0b9415ae44e8008025a0d2f37d177dd6a264436d0013c5fed3678d141fb4fedddd1a240646c9f0ba6460a05e9a5f237acc7b9ae86ab3cdb0dae4971c541f93ad36a5e2c10add0e7ead4134","0xf86c80850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae68806d0c724bdc5f0008026a09b934d5b9b13a0083b6758c58cfed37ed8593581639e5cf55f7bbe652953382fa07ae72426c894e50ff0a8b94e619a1b548b0483fafcd1168f2fa6bace8e56841d","0xf86c11850130e0b4c0825208944a8c8c8917591a4c1eeb1ba9049a76d1761bbae6880ca2e84ed75498008026a010329028e975336f76b47a9cedc0ee640c4dd19b890d42b6833f502d15a1c399a0310de8a2b06ef14d4eff7bfc364e10f16626f25414a8ef8658bd6471b495c5b2","0xf9078d82ef2885012a05f20083023dbe9461935cbdd02287b511119ddb11aeb42f1593b7ef80b90724dedfc1f1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000004400000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7e4171bf4d3a00000000000000000000000000000000000000000000000000000000000022146594c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343a400000000000000000000000000000000000000000000000000000171adbe5c8700000000000000000000000000000000000000000000000000000000000005a00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006600000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7e4171bf4d3a00000000000000000000000000000000000000000000000000000000000022143505800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea3439900000000000000000000000000000000000000000000000000000171adbe0c3c00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000006425bb021dabd5d6b443a1ab47b003a1b7a27d4b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f45e793753e5c92000000000000000000000000000000000000000000000000002b5e3af16b188000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343a700000000000000000000000000000000000000000000000000000171adbe351f00000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ba0d2b3266518073de150234ee29b34e74d8333a83f6e98c2681ca3f1903d264598a04ed2cc0972dd834f05d7018e66480b5e40bc260461c118049c9b35ba01d3ba21","0xf9036e83031c7985012a05f200830119419461935cbdd02287b511119ddb11aeb42f1593b7ef80b90304dedfc1f1000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000998497ffc64240d6a70c38e544521d09dcd232930000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000059ce129000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ea343f300000000000000000000000000000000000000000000000000000171adbf945900000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f47261b0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ca0056b1d709fb718fe746e782c4319a57eea7d36ff000a3ee3c0717609d4c1a186a03a72060940b046403afb27aca5ad3eccfe72e786e476682ca115def0db556224","0xf8aa8085012a05f200830186a0948e870d67f660d95d5be530380d0ec0bd388289e180b844095ea7b3000000000000000000000000ff8e926d0d92b5da930f5534a79e5b821f719f8a00000000000000000000000000000000000000000000d3c21bcecceda100000025a0cf0599d667d0f637eacde685207fdbed082d57234ec09f367753ac22b8f1e542a07f276fe195b69b55c353dc4a20edea7fa1d69583810788386607297da7098463","0xf8ac82022b85012a05f20083030d4094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb0000000000000000000000008d8516b501662d774237355aca1f3c56baca5612000000000000000000000000000000000000000000000000000000000098968025a0241328ae31b69645de0854bd142641b92b6666f629ea1778497d0a5197c64aa3a01cb213d36f747002e0913e83b5a5476ec09030e1c44043408cfed22615efe028","0xf86b0285012a05f20082520894ac3e543d1ea0bbfef0975e60837e802199a7404787038d7ea4c680008025a0a2f95712afd16177fa460c6d84893ab123ec08ab412b1d348c595a5bf047032ba068556fedfb8a7094b006499514ba4c2dd1d22abda6c549ee87ed066671ab76bc","0xf86c0885012a05f20082520894797dbfab26308010199f0b18c97c1c554dd119f988023539c0512e18008025a005ac984be4f5552f0e90ae50675e402312559c6c8cddb7f82ada27aacc6b8883a069fbf4ad8567d6ad8b797c1e0e710f30dd6c659bfc31e3305e2647628e9e3ed9","0xf86b4c85012a05f20082520894b1793c313cc6bcb656ffdcac736f9f3f009afc2387038d7ea4c680008025a0ec2a48cb1c07632ee0aa3b816e5db25f10af48710f02aa8421f186393aacba04a06f2272b7baafaee865c82e5f7b4550138ef2b5ce3cdfdc8d834dd39eb44638e0","0xf86c0385012a05f20082520894c180e0f1300c4d9a76804d9aba7943b8956e059c88013fbe85edc900008025a04e1c1829eb7764eda4f827497d2bdee68150bbe3feaa7af50a62504eb2392d3fa06bee4a949f6611330f285c8372312816e8ec3572168e3032d7c490af9ee2503b","0xf8a90e85012a05f200828dc694d341d1680eeee3255b8c4c75bcce7eb57f144dae80b844a9059cbb000000000000000000000000a3dff789b8ac4ed21927bbfbc2ee327843db19940000000000000000000000000000000000000000000001a812abac7ddfb6e6b91ca0d708a403634a643746c4823c8837a30ab3531a44d3c4d28af322ecd7a51f98d0a05100866430802fd08c4ac4e1588654a203fa251fdcb19c0a2444b1ddcb84b2ec","0xf8aa0285012a05f20083030d4094a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4880b844a9059cbb00000000000000000000000068450d9b6d5d3d352bb2e632083808ddc7d09f720000000000000000000000000000000000000000000000000000000005f5e10026a0c58236a95b6ff5ec43f980922dcae557058530fdb3910a1c6095b44910a70a53a018736a1bae462947927b0b1cc26c25d66fffecd1d2b1df3b17815f52247deda6","0xf86c0185012a05f20082520894c75804f4b0c9447a3c55ed5cdf5f2cde42c2302e88016345785d8a00008026a08ad07e33e604963c3ca221ff4ffcfa13e9c73e7d180b8dbac391d4adba03d225a032ca129db619cb8891c7b21b39a035fd7813de24d56a5b14d50b285e7b4a1df9","0xf86b1185012a05f20082520894ba487bf6f05b0d34db31617170d3c463baf588ee871831fc5c265e458026a046bb7c63786b51a9ca0ec7cb9ad8ea55acc2ac42a1cfc8a899f27170de1b329ea0399db1a294f148fffa3c726676933850ac6b96045852a5c95c16413956273fcc","0xf8ab81bb85012a05f20083030d4094514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000ac3e543d1ea0bbfef0975e60837e802199a7404700000000000000000000000000000000000000000000006c6c9f3f601961400025a0c178b6c11b06ef1387bc53d193bb9eaa83f9ccdacf70a0d8f877867d93e32ee4a0489d61acd72c70f2a53d691172566fc5aacc99140c2698e40dfc207a6f491775","0xf86b0185012a05f200825208948d8516b501662d774237355aca1f3c56baca561287038d7ea4c680008026a0eabf0fcab25a5a1c14860615aaae566acb6917e0d0c7b24345ba0e98a2aa6672a05ac1ad6fe424b12f068e3515eb4ad131dde4bf39e2a30f2d85242b21be349c90","0xf86c0285012a05f20082520894d5fbda4c79f38920159fe5f22df9655fde292d4788102e9c1a296edd738026a0173435d0577300a279f0681fc8900ffdd202d592798a14044751414bbf52ae21a04656f95c4702d2e10490b2e4a88be781cc00ae72c12943082c524baee47d6088","0xf9010b8216be85012a05f20082a921944976fb03c32e5b8cfe2b6ccb31c09ba78ebaba4180b8a4304e6ade74138d0a668bfa50b16d4628865b94618130db944e48326a49d17f23be3ead1100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000026e30101701220b7add76198a03a31d015fead8a17b930ffc7a8bc8428a02a48d5746e9578cd99000000000000000000000000000000000000000000000000000025a0c147ec8d741622c2bfee163d59ab0dee4866794fc816411965def3380282a301a026b216286050e7347d4a4ed97bd9e2be015c815dbe1a4d6e19f63c28f2b15b2d","0xf86b4b85012a05f2008252089468450d9b6d5d3d352bb2e632083808ddc7d09f7287038d7ea4c680008025a0db5d888aa9f844b2566bb608a13fa3a7a586ced4ecbfe120a113e9ba9ea9c18ca0611c29cca55e4f3f99c4afdd7e5b89f4aa88374ed439d7b96a1c9cdad40bf3cc","0xf8aa0385012a05f20083030d4094514910771af9ca656af840dff83e8264ecf986ca80b844a9059cbb000000000000000000000000b1793c313cc6bcb656ffdcac736f9f3f009afc2300000000000000000000000000000000000000000000001156cf785cb0b1000026a05c1289647a1fb85aba8d3d9f8c19a9a17bc562dce4db6d95c5a3908263ebaaf6a016edebd84fac5df1e75bafcf180a80b4f4922c13842aa4b4853f2f54300b998f","0xf86b2885012a05f200825208940ada51acc249f6a1b320be335527b127d03a9fe887038d7ea4c680008026a0b98633766bbe61e9caf0d5dc01d22ca50d305f505551e237b3f64b83bfb6c726a060f71d2d83df97cbd8799e73db215fed9ba9e5cbcb0206ce89b46c00a471dc2f","0xf86c8085012a05f2008252089485837fb5882e36d054ab518ba2f951aefa7815cc88570fa87381a268008025a03ba379ca7dc36169a9c35e7259d735c36abba5fbd33a2e517a05578310581f79a023fbf0aaff2ff671696ff5b9cad09ce589e7896337ef7040df4d802ffba9895d","0xf86e8306dcc6850115295e8082c350946c94ed48e15dc68c56e2c146239a3b39e5ba41b9878e1bc9bf0400008025a0481c6c8ee6991a43aec2bfb78cad55501b9fbc22ea3e9a9ece44e51bd585245da067bbe9703eec584d67b69efc960e28c1c06f27e82c883188326adad243e80720","0xf86c8085010c388d0082520894015f369c8cdfcab34a2ef4f448e0145d86a4e5188801cdda4faccd00008026a0b04fa2f0d8f6af66b900531f12e05a685d532729135cf11af5ed278c9d5892b5a03d4a543408d3ec1f84e5fb6834ef21574b980d86d8d2f00f5519c456bbb1bb6e","0xf86d8250d185010773d9008252089466c7c8ac1b9680a8abf07ff03a9e637cd742c0eb870197bfcd8f9f00801ca0f2cbce7d1e2124cd94dd11cffcb02daf8413bff952d551e97e0f7a0f3778570ca04f0d79cfb4a9709f0fdbb7bb073e7704e8723e3b990009d3b6ed15bda62ce9a2","0xf86d827dfa85010642ac008252089449d148b76ce691db6243836e8cce651b846ca33787071afd498d0000801ba058e07c497f0be5c91643a43b5e780a4760b34b6df95d13669302dd1506f8dce1a04b4f140b5b3fb36f07b44dd12088b5ea46a6608ffccf1cff1493f2464e131fb7","0xf86c8085010106978382520894ac54b0f52f314f1efbef245a5416fd5d7e381b7188017896703a310000801ba017f7a0e897474e671e1b0155f725d04a15442bf2baa2280162fa180c6162afb2a00264ec07ef2ff50a419a6bcd9b4384347c8d6091fd937ac905596f9aae96cfae","0xf86c018501010697838252089474381d4533cc43121abfef7566010dd9fb7c9f7a8805e1b5089f4a9bd0801ca0550e0a23b9852355f1b551a6a80888ba0c72c89b4ada3b096a9cffa44af030dca02a3888743bcd0eb372a99fdc458d047d40274bb20accae5175add1b7e03b8720","0xf86982cec484f8210f2082ea6094693c188e40f760ecf00d2946ef45260b84fbc43e8084ea8a1af01ca0f55050bd36cbe68870765070ce57da5ac12ba27fe6bdffe8827b31c8c259aebfa04beea357135e2a6abec635f67a7559f02a037e6828f4f4d18c651044082baca6","0xf86d82029984f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb328803c6eb14d70da00c8025a0afae89a75d02056fdbf34f7ca94dbd5013f895d2eaebf70a6625c8494315e487a05c60dd0a235da1e89b3fa5f01b2c7f9ddf14c66b972bbf94f578e0c2c2a35e1e","0xf86c82047f84f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb3287d8cb359b3b99e08025a02c63acd03a982f0ff65ef35fdcf6a167c05e7e66519eb2c6e2b216c3084b8a2ca05cf9ae52116814d0d8b27be4eb6625db767a3cd7aac3203d92e8595110ee54a0","0xf86b0e84f3e6f70082520894c2eabefe82d16d90aafeeeab800504030e01aa69880131888b5aaf00008026a0accd356e5576a0760c632cfd03f605d660ccaa5174c4e2c391babdcb624c88ffa05a91ed2c3b95c8c7ffde91a3075c29b3a177ed01917168122393d8c69789d5ac","0xf86a818e84f3e6f70082520894d7b9a9b2f665849c4071ad5af77d8c76aa30fb3288010baa6ef0d8bf8b80259eacaff80ee360ff701064d1ce214ec2daad7281bdd7d4e94e73a53159af5aa0743fe78b9a453099fd5c30470fb9e219b145ed89eba3bd642ab81b649e5a9db8","0xf86a1784ee6b280082520894f6888a28d242cc547896e5fcfddb73519c566ccd872aa1efb94e00008025a0bd604d4c7332190c39f6cd626d3e9f5fe7f71bc54e10f5b491c5eb5b4ff2e1eba065f91c5fdf37f193a50befa80656d04ba22b406e8dea3f8178097912e96bc7d8"]},"version":"2.1.0","currentBlock":9937414,"lastValidatorChange":0,"lastNodeList":9936729,"execTime":1625,"rpcTime":1300,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x4e65746865726d696e6420312e372e352d302d6139386364356233302d323032bc4a7f72366a28756c773085f7286ca37fa67ec2dbfe2cb859d261de899688ac53c5948ccf380af051f33b7039278ee267ff1c52a49263f67769fbee08f36f5c00","gasLimit":"0x7a1200","gasUsed":"0x0","hash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x2764d7","parentHash":"0x092a106d8b102323f87cfc676950d3afaf0d11e2823a21cb7026e91fd79b926c","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":["0xa00000000000000000000000000000000000000000000000000000000000000000","0x880000000000000000"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x261","stateRoot":"0x90c5230d593c56a2356a6dc0863f491dd04a29a167a31da20a549064f74172a6","timestamp":"0x5ea34439","totalDifficulty":"0x3a919e","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]},"id":1,"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","block":2581719,"r":"0x3e4525e6d92dcfc1a9f3d317caf39a64805f96e2f12de577a6dff6b4a31fbea8","s":"0x7ff801e9160e4f94ea5c1e0b93c6bf6945095e970892294c99bec2a35b6c28b0","v":28,"msgHash":"0x5c4bed5dc46bec44bd21e625f45f2e8921a0f3351be2b19abc52f08d029cd784"},{"blockHash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","block":2581719,"r":"0x4c2b6e8468435ac0c122a4da90f472280b7405eafdd125323fa160905999dacc","s":"0x70381d6f1cb2a36c64a1a981ea4cd3656edb9f68e544840253a4132875867636","v":27,"msgHash":"0x5c4bed5dc46bec44bd21e625f45f2e8921a0f3351be2b19abc52f08d029cd784"}],"transactions":[]},"version":"2.1.0","currentBlock":2585900,"lastValidatorChange":0,"lastNodeList":2561645,"execTime":132,"rpcTime":35,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x4e65746865726d696e6420312e372e352d302d6139386364356233302d323032bc4a7f72366a28756c773085f7286ca37fa67ec2dbfe2cb859d261de899688ac53c5948ccf380af051f33b7039278ee267ff1c52a49263f67769fbee08f36f5c00","gasLimit":"0x7a1200","gasUsed":"0x0","hash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x2764d7","parentHash":"0x092a106d8b102323f87cfc676950d3afaf0d11e2823a21cb7026e91fd79b926c","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":["0xa00000000000000000000000000000000000000000000000000000000000000000","0x880000000000000000"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x261","stateRoot":"0x90c5230d593c56a2356a6dc0863f491dd04a29a167a31da20a549064f74172a6","timestamp":"0x5ea34439","totalDifficulty":"0x3a919e","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]},"id":1,"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","block":2581719,"r":"0x3e4525e6d92dcfc1a9f3d317caf39a64805f96e2f12de577a6dff6b4a31fbea8","s":"0x7ff801e9160e4f94ea5c1e0b93c6bf6945095e970892294c99bec2a35b6c28b0","v":28,"msgHash":"0x5c4bed5dc46bec44bd21e625f45f2e8921a0f3351be2b19abc52f08d029cd784"},{"blockHash":"0x2efb5de123762987f1b5e93cac54cbe0ac2620f919736e830be425336c164b9e","block":2581719,"r":"0x4c2b6e8468435ac0c122a4da90f472280b7405eafdd125323fa160905999dacc","s":"0x70381d6f1cb2a36c64a1a981ea4cd3656edb9f68e544840253a4132875867636","v":27,"msgHash":"0x5c4bed5dc46bec44bd21e625f45f2e8921a0f3351be2b19abc52f08d029cd784"}],"transactions":[]},"version":"2.1.0","currentBlock":2585901,"lastValidatorChange":0,"lastNodeList":2561644,"execTime":129,"rpcTime":30,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":{"author":"0x03801efb0efe2a25ede5dd3a003ae880c0292e4d","difficulty":"0xfffffffffffffffffffffffffffffffe","extraData":"0xde830207028f5061726974792d457468657265756d86312e34312e30826c69","gasLimit":"0x989680","gasUsed":"0x1a04ec","hash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","logsBloom":"0x00000484104000400041040888000000504002000001021000400820a24000a080c1009200004020300000020a00c030040084041000080101100200040100000180000002488001000140688a0000044c000020836700000002a000040883220d300000020000041300840001202e241500000480000a82204288100048026080601a00144000000000000001118014100006a602406000002801488004133020800118c0040000000300420c00400050100120010051200000402200000842424001021480040025420000030108531000400a00100020140100015000302000000080400010c1800080801020800205200010a40000000020080000000000","miner":"0x03801efb0efe2a25ede5dd3a003ae880c0292e4d","number":"0x114b8c1","parentHash":"0x2aed9af5827bd4d1e2eeb4fcda41a26178b4e766bbf7705670247d39e7587930","receiptsRoot":"0xf9aeb295160b9d5c7b81101f5be4e781a08b0933116c098a54e4ec4561e9ae1c","sealFields":["0x8417a8d151","0xb841e6054c4674a49af07b6a9d042201d61db075cd54c36342bd49c66cdd52e914f00641794a74b8078701fc5af39ed2df33bd942e14d7dc22e25eefc062990a0e9601"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","signature":"e6054c4674a49af07b6a9d042201d61db075cd54c36342bd49c66cdd52e914f00641794a74b8078701fc5af39ed2df33bd942e14d7dc22e25eefc062990a0e9601","size":"0x1d8a","stateRoot":"0xd3a93aeea51d27704aebe2559118738fb3d9420ea9f5a5bd1689260b37e97fbf","step":"396939601","timestamp":"0x5ea34544","totalDifficulty":"0x11275b200000000000000000000000483996717","transactions":["0x45a91f747dea2369dc5696def244829af6bf257673a1053a974e9bd895b531db","0x5066caefaee1874104bfb9e77ed2ca7a082e937c7faecba5afaef0a81ce77b6a","0x0f8dd237ec50366ad9d2b05a8c2bc8936053c0297684ecd1f17752b566e47b50","0xe8d761b0ffe0828643258c9460344d6f514b5538c502c2472bf8e0a0077a5c73"],"transactionsRoot":"0xb5ee4a8a8519126ba2c4193e156d7ba8e4fd165f8341801345dfda426c0337d5","uncles":[]},"id":1,"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","block":18135233,"r":"0xb4b25305fa2a4d170bd95c42d40eaa44bc58055953ff229b4a88e673184ca3b6","s":"0x710d005123725944b916201f41af08b3d05e3109ea5b5b8dc4fa691d976dacee","v":28,"msgHash":"0x283a84c906fdce481be2a79fae5b206f82eab5e76d52a233a2525c7fb16af1ea"},{"blockHash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","block":18135233,"r":"0xd964f3720766c4811b44794bed586acf8377e519d4344fde6c53f42900d97081","s":"0x286c205e89a015c9098c8c3b7dbc0c9b5e964889be371b0468219327b6a615a8","v":28,"msgHash":"0x283a84c906fdce481be2a79fae5b206f82eab5e76d52a233a2525c7fb16af1ea"}],"transactions":["0xf88b82cfc385028fa6ae008307a1209463294a05c9a81b1a40cad3f2ff3061711163039380a4daa6d556000000000000000000000000000000000000000000000000000000000000000077a0beca206daa0359a963eac23d82a8aca0285fd3712a547d318102c95b5b9b2310a067a0755c3b23676d6c1aaff34f2706e751020697a75399640a2fc76065858596","0xf88c8302338a850218711a00830f424094bb4617d26e704ac0568e1cbf5232990a8b7846a480a4af14052c000000000000000000000000000000000000000000000000000000000000000078a0c5ff2539ca6f3c3d0388a6305f5161488e4128dd0e07a4551944c4faeed69373a00c076857bd95d9c623ba66d7bfb4f462c1173b28aa7e932a6344f2f9f9828cab","0xf88b8304487f843b9aca00837a12009482bf5164c3b82661c7f025b40f605d0ea5ea44d680a491b7f5ed00000000000000000000000000000000000000000000000000000000000049b61ca0e5c31a9054023adbc994b61e76732016f4e9d91c059c8312d72f13c8ec1c9667a02ef52e0e0668c8ad20ce02f51da57a247dcd6284cf6a2b46354636fc42b61214","0xf9198d830418b9843b9aca00833d090094f8fa04d0b67c27a2a7c269259a31d643c8e1534780b91924d559f05b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000000000000000000000000000000000000000000041000000000000000000000000bff07a750a5e1f619ddf860170b63e1814c02c16000000000000000000000000981a38e9d6e46cf89bb11e77efcfbbaefd587fab00000000000000000000000030f94b7a9407df4657447e6ead69c7af5f8b85be000000000000000000000000a9ca1c23c2d452315b547a86e09bf4dfa18d8be20000000000000000000000009e459a0e9002a2d9f4d4613d2ffa82ad32cdb6f6000000000000000000000000f15e0237a1b67af37bfd759bff3e22e1f5b1f3e3000000000000000000000000097f63361ffbb2bdc2f387be40e032de1a8d2fc1000000000000000000000000838861eb9a54dbe12c3e8a01bd99e1a5eb92f790000000000000000000000000098c242645ff9ae75d16851c8fc46ac2fabe8bed000000000000000000000000ec8f7f48dba37c7a0681c3f69b46344f759cab6c000000000000000000000000545d4c755b6c7fa86c85245e3f013060b5d493290000000000000000000000008a7af1d8aeac5a6d95776bde4d234458f91b834400000000000000000000000001caf0b35839698a15e35810c413159599a83757000000000000000000000000f39b7da00048e60c69485694692b3c556084b231000000000000000000000000ca3c0b6d6c1897abf9ab6488cee7b5540a76a439000000000000000000000000e53c58037bf0eef22e5f987378d05880aa770d610000000000000000000000005dbbe6dd162cfa97d320a59bc4352521d62d3fce000000000000000000000000db5e8f851c1e48cb5b9dce5554390109544a386a000000000000000000000000b8352034fa41976ddcf4a47dc9e9ed7485b1234e000000000000000000000000cbae71db257ba1f83eba3a019ecb6e9c98301a29000000000000000000000000fdafa187b229d03b4722b87df9a0bc34cb6260fd0000000000000000000000007780e64bb87f1f20084a4eb56c378315bf7a5e75000000000000000000000000143415e993ce3ade9c411419368642771fbd78b000000000000000000000000079b7363df0b7234359c3caa8442cdff7dc0f68f60000000000000000000000004052db04a3539648dd05b61b8ffa79644de0804a000000000000000000000000e189eb3483eca0c4e36fb60ceb98c2293aa711800000000000000000000000007eee255d30728709aa4bc5daf97ba3776ee07a59000000000000000000000000317366617e3bdbc7081d6602115cee647487a489000000000000000000000000d233c18f58837ed0107f8cff383f80eb42beb9a1000000000000000000000000a35ca26144976fc29c3534d455e6c9b73e670dd70000000000000000000000008dbaa5a12be71b9b37aa4b6bb56fd7b50193b06d00000000000000000000000064f1271c01cbdda7e33aaca5a0e666741e38189a0000000000000000000000000a1c771da2f0fe53d22f02a1291fc5926836e15c00000000000000000000000008e8b15ee8999cf98642b03a777d842b216dbd090000000000000000000000006ded203e32a01d1c3bae4b99652859bd9035f250000000000000000000000000db68dfdfe880e9f851b01d084fdd1844f3af133900000000000000000000000081a732ac0e84a0046bf356a31420e795458fb6b80000000000000000000000003c7c4ef505f15a44be502f77c62fc24a92340e8b000000000000000000000000192a3e522dbee627adc355bcd0aa6bd0b1aee226000000000000000000000000643d7f36ba4e915f34d123b699fa9401fab47f9e00000000000000000000000008b6e838fab1d665f781f1da588bed207d69d210000000000000000000000000106f2e71d9cd346af23100d325935fe4141ffa460000000000000000000000000c8727f550b7110b630999921959b0da53838db400000000000000000000000092031fa56eb30e2fab895a10350faf8f2474f8b700000000000000000000000001e94fa55e07a45e6a8ce263158115534ca94299000000000000000000000000dd05ef6f307fe4302e759d09464cbe2bd2531c2a000000000000000000000000641c385928f6a4216828b6750afd06296eb00d64000000000000000000000000df04c1807a36bf70493afe107f02ba4703c5bd55000000000000000000000000bb5e986602fb064bc7b90a1dbce973d67374d7db000000000000000000000000363a1e5710899fe33dfcf881a297aaa279264459000000000000000000000000460c394e24fef4ccd5e4555e00661f19f71d605a000000000000000000000000033d1b2bac384f302e0c68eec248bf750db40ea8000000000000000000000000a3b8d524eeca001cbbf782fc8d719fbef3149169000000000000000000000000e28644fca9365f12763f9784920ff821eb54b8bf000000000000000000000000803404284433d49d192efb7699a47b7a2c43ba66000000000000000000000000ece072572872da39db73e28c4d6fb818e79ae324000000000000000000000000f6cd296865260065d8e407c4c9a18bd5057ba596000000000000000000000000aea033ffcda37c606ea90d2ea73b1cb82c8e807d0000000000000000000000008d4dd9cb570cc954ff4d47297c3519716c7cfc9e00000000000000000000000082a253abe6a2aa292c2f4814710fd1a57c31f8360000000000000000000000004de65a4823ba6a52107004616edb242a29237a3400000000000000000000000032f2dd75c3e4784d22ef5708d6cdd9978703d10800000000000000000000000050d50ce0ae2e2a0e4cf8d75f2f32e0e303f98b0e0000000000000000000000009fb10ee238ffba47fce9ac87c6b9561cf325d15c0000000000000000000000004c8759a990821aba1c84079e7bb6a4ef364cf282000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078a0a1e0d73c76f6c07ae8337ccf0744aa3f86df3bc43483f5265669199d2e557fbca05b8d90c2f2ca037c4648128104a693dc9cdb892ebf5f2e78800a81de305f0023"]},"version":"2.1.0","currentBlock":18150181,"lastValidatorChange":0,"lastNodeList":18098311,"execTime":438,"rpcTime":250,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":{"author":"0x03801efb0efe2a25ede5dd3a003ae880c0292e4d","difficulty":"0xfffffffffffffffffffffffffffffffe","extraData":"0xde830207028f5061726974792d457468657265756d86312e34312e30826c69","gasLimit":"0x989680","gasUsed":"0x1a04ec","hash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","logsBloom":"0x00000484104000400041040888000000504002000001021000400820a24000a080c1009200004020300000020a00c030040084041000080101100200040100000180000002488001000140688a0000044c000020836700000002a000040883220d300000020000041300840001202e241500000480000a82204288100048026080601a00144000000000000001118014100006a602406000002801488004133020800118c0040000000300420c00400050100120010051200000402200000842424001021480040025420000030108531000400a00100020140100015000302000000080400010c1800080801020800205200010a40000000020080000000000","miner":"0x03801efb0efe2a25ede5dd3a003ae880c0292e4d","number":"0x114b8c1","parentHash":"0x2aed9af5827bd4d1e2eeb4fcda41a26178b4e766bbf7705670247d39e7587930","receiptsRoot":"0xf9aeb295160b9d5c7b81101f5be4e781a08b0933116c098a54e4ec4561e9ae1c","sealFields":["0x8417a8d151","0xb841e6054c4674a49af07b6a9d042201d61db075cd54c36342bd49c66cdd52e914f00641794a74b8078701fc5af39ed2df33bd942e14d7dc22e25eefc062990a0e9601"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","signature":"e6054c4674a49af07b6a9d042201d61db075cd54c36342bd49c66cdd52e914f00641794a74b8078701fc5af39ed2df33bd942e14d7dc22e25eefc062990a0e9601","size":"0x1d8a","stateRoot":"0xd3a93aeea51d27704aebe2559118738fb3d9420ea9f5a5bd1689260b37e97fbf","step":"396939601","timestamp":"0x5ea34544","totalDifficulty":"0x11275b200000000000000000000000483996717","transactions":["0x45a91f747dea2369dc5696def244829af6bf257673a1053a974e9bd895b531db","0x5066caefaee1874104bfb9e77ed2ca7a082e937c7faecba5afaef0a81ce77b6a","0x0f8dd237ec50366ad9d2b05a8c2bc8936053c0297684ecd1f17752b566e47b50","0xe8d761b0ffe0828643258c9460344d6f514b5538c502c2472bf8e0a0077a5c73"],"transactionsRoot":"0xb5ee4a8a8519126ba2c4193e156d7ba8e4fd165f8341801345dfda426c0337d5","uncles":[]},"id":1,"in3":{"proof":{"type":"blockProof","signatures":[{"blockHash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","block":18135233,"r":"0xb4b25305fa2a4d170bd95c42d40eaa44bc58055953ff229b4a88e673184ca3b6","s":"0x710d005123725944b916201f41af08b3d05e3109ea5b5b8dc4fa691d976dacee","v":28,"msgHash":"0x283a84c906fdce481be2a79fae5b206f82eab5e76d52a233a2525c7fb16af1ea"},{"blockHash":"0x5d26520300d98a8098b0f279e3afd292232050f1b398848316edb8d2543cd8c4","block":18135233,"r":"0xd964f3720766c4811b44794bed586acf8377e519d4344fde6c53f42900d97081","s":"0x286c205e89a015c9098c8c3b7dbc0c9b5e964889be371b0468219327b6a615a8","v":28,"msgHash":"0x283a84c906fdce481be2a79fae5b206f82eab5e76d52a233a2525c7fb16af1ea"}],"transactions":["0xf88b82cfc385028fa6ae008307a1209463294a05c9a81b1a40cad3f2ff3061711163039380a4daa6d556000000000000000000000000000000000000000000000000000000000000000077a0beca206daa0359a963eac23d82a8aca0285fd3712a547d318102c95b5b9b2310a067a0755c3b23676d6c1aaff34f2706e751020697a75399640a2fc76065858596","0xf88c8302338a850218711a00830f424094bb4617d26e704ac0568e1cbf5232990a8b7846a480a4af14052c000000000000000000000000000000000000000000000000000000000000000078a0c5ff2539ca6f3c3d0388a6305f5161488e4128dd0e07a4551944c4faeed69373a00c076857bd95d9c623ba66d7bfb4f462c1173b28aa7e932a6344f2f9f9828cab","0xf88b8304487f843b9aca00837a12009482bf5164c3b82661c7f025b40f605d0ea5ea44d680a491b7f5ed00000000000000000000000000000000000000000000000000000000000049b61ca0e5c31a9054023adbc994b61e76732016f4e9d91c059c8312d72f13c8ec1c9667a02ef52e0e0668c8ad20ce02f51da57a247dcd6284cf6a2b46354636fc42b61214","0xf9198d830418b9843b9aca00833d090094f8fa04d0b67c27a2a7c269259a31d643c8e1534780b91924d559f05b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000010e00000000000000000000000000000000000000000000000000000000000000041000000000000000000000000bff07a750a5e1f619ddf860170b63e1814c02c16000000000000000000000000981a38e9d6e46cf89bb11e77efcfbbaefd587fab00000000000000000000000030f94b7a9407df4657447e6ead69c7af5f8b85be000000000000000000000000a9ca1c23c2d452315b547a86e09bf4dfa18d8be20000000000000000000000009e459a0e9002a2d9f4d4613d2ffa82ad32cdb6f6000000000000000000000000f15e0237a1b67af37bfd759bff3e22e1f5b1f3e3000000000000000000000000097f63361ffbb2bdc2f387be40e032de1a8d2fc1000000000000000000000000838861eb9a54dbe12c3e8a01bd99e1a5eb92f790000000000000000000000000098c242645ff9ae75d16851c8fc46ac2fabe8bed000000000000000000000000ec8f7f48dba37c7a0681c3f69b46344f759cab6c000000000000000000000000545d4c755b6c7fa86c85245e3f013060b5d493290000000000000000000000008a7af1d8aeac5a6d95776bde4d234458f91b834400000000000000000000000001caf0b35839698a15e35810c413159599a83757000000000000000000000000f39b7da00048e60c69485694692b3c556084b231000000000000000000000000ca3c0b6d6c1897abf9ab6488cee7b5540a76a439000000000000000000000000e53c58037bf0eef22e5f987378d05880aa770d610000000000000000000000005dbbe6dd162cfa97d320a59bc4352521d62d3fce000000000000000000000000db5e8f851c1e48cb5b9dce5554390109544a386a000000000000000000000000b8352034fa41976ddcf4a47dc9e9ed7485b1234e000000000000000000000000cbae71db257ba1f83eba3a019ecb6e9c98301a29000000000000000000000000fdafa187b229d03b4722b87df9a0bc34cb6260fd0000000000000000000000007780e64bb87f1f20084a4eb56c378315bf7a5e75000000000000000000000000143415e993ce3ade9c411419368642771fbd78b000000000000000000000000079b7363df0b7234359c3caa8442cdff7dc0f68f60000000000000000000000004052db04a3539648dd05b61b8ffa79644de0804a000000000000000000000000e189eb3483eca0c4e36fb60ceb98c2293aa711800000000000000000000000007eee255d30728709aa4bc5daf97ba3776ee07a59000000000000000000000000317366617e3bdbc7081d6602115cee647487a489000000000000000000000000d233c18f58837ed0107f8cff383f80eb42beb9a1000000000000000000000000a35ca26144976fc29c3534d455e6c9b73e670dd70000000000000000000000008dbaa5a12be71b9b37aa4b6bb56fd7b50193b06d00000000000000000000000064f1271c01cbdda7e33aaca5a0e666741e38189a0000000000000000000000000a1c771da2f0fe53d22f02a1291fc5926836e15c00000000000000000000000008e8b15ee8999cf98642b03a777d842b216dbd090000000000000000000000006ded203e32a01d1c3bae4b99652859bd9035f250000000000000000000000000db68dfdfe880e9f851b01d084fdd1844f3af133900000000000000000000000081a732ac0e84a0046bf356a31420e795458fb6b80000000000000000000000003c7c4ef505f15a44be502f77c62fc24a92340e8b000000000000000000000000192a3e522dbee627adc355bcd0aa6bd0b1aee226000000000000000000000000643d7f36ba4e915f34d123b699fa9401fab47f9e00000000000000000000000008b6e838fab1d665f781f1da588bed207d69d210000000000000000000000000106f2e71d9cd346af23100d325935fe4141ffa460000000000000000000000000c8727f550b7110b630999921959b0da53838db400000000000000000000000092031fa56eb30e2fab895a10350faf8f2474f8b700000000000000000000000001e94fa55e07a45e6a8ce263158115534ca94299000000000000000000000000dd05ef6f307fe4302e759d09464cbe2bd2531c2a000000000000000000000000641c385928f6a4216828b6750afd06296eb00d64000000000000000000000000df04c1807a36bf70493afe107f02ba4703c5bd55000000000000000000000000bb5e986602fb064bc7b90a1dbce973d67374d7db000000000000000000000000363a1e5710899fe33dfcf881a297aaa279264459000000000000000000000000460c394e24fef4ccd5e4555e00661f19f71d605a000000000000000000000000033d1b2bac384f302e0c68eec248bf750db40ea8000000000000000000000000a3b8d524eeca001cbbf782fc8d719fbef3149169000000000000000000000000e28644fca9365f12763f9784920ff821eb54b8bf000000000000000000000000803404284433d49d192efb7699a47b7a2c43ba66000000000000000000000000ece072572872da39db73e28c4d6fb818e79ae324000000000000000000000000f6cd296865260065d8e407c4c9a18bd5057ba596000000000000000000000000aea033ffcda37c606ea90d2ea73b1cb82c8e807d0000000000000000000000008d4dd9cb570cc954ff4d47297c3519716c7cfc9e00000000000000000000000082a253abe6a2aa292c2f4814710fd1a57c31f8360000000000000000000000004de65a4823ba6a52107004616edb242a29237a3400000000000000000000000032f2dd75c3e4784d22ef5708d6cdd9978703d10800000000000000000000000050d50ce0ae2e2a0e4cf8d75f2f32e0e303f98b0e0000000000000000000000009fb10ee238ffba47fce9ac87c6b9561cf325d15c0000000000000000000000004c8759a990821aba1c84079e7bb6a4ef364cf282000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078a0a1e0d73c76f6c07ae8337ccf0744aa3f86df3bc43483f5265669199d2e557fbca05b8d90c2f2ca037c4648128104a693dc9cdb892ebf5f2e78800a81de305f0023"]},"version":"2.1.0","currentBlock":18150184,"lastValidatorChange":0,"lastNodeList":18060209,"execTime":266,"rpcTime":128,"rpcCount":1}}]',
+ },
+ "eth_getStorageAt": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x647261676f","in3":{"proof":{"type":"accountProof","block":"0xf9020da0118380d6de71cbde67e07119819ab5d0b5949fe522768c4db003d64fa95c6749a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479404668ec2f57cc15c381b461b9fedab5d451c8f7fa02a07fb579d89aad0cd11bd1f28dd729c47972c72c3cb23f06f090ab53ba14df3a0231be1dc81c2377ce4dfad7884bfe73d359a745221a6cd27d4e56c2a1da57d8fa045337ea57543ec8861eca9dc664029647deea1851bbf007a5eeab7a1ab4b1365b90100a000020f50404a2aa08c8e812087302d02a3ae08173091b026200116216063fe48240c0620d0480c495201468306815349720002190623c184121902d03881054016200a5841460141a1581d0058c0a22e28c0120989241c7440948e5aa3203684a42400226220549b3c9064a53688801de037710a3402508ca43bb9439230a811203148b0800050d2000308c6e0bc001116110248945314f116431aaa76348a865c6088e018820697742091c10099c2014054046162ba21402401e3188c0840546e080330a469048401cc65461189144040d08e00e52a0400c100180f8227d8201c082093051310c26089000013f5004b284c0a4a460a00200402001a00b61a8707d9bfb0ed04938397b75d8397d744838bbcdb845ea46e628c73706964657231310802087ca0ed3c96fa8eeec30997bcd737bc2f81ea200a47df679ccfcac946a0182fbc35a788b273db68210e2ca6","signatures":[{"blockHash":"0xafe0b6aec651d567d007e70506be2f2f09035d3c3933692866395048170cb4e3","block":9942877,"r":"0x7e3b3cb7ab976d57c4cef2e7023a65bc24215186fb765e415ad76baa73589e60","s":"0x1a12ea7f04a2830dfde925fc5ef0f542c112751970d9f186b16367cc5ab0ce7d","v":28,"msgHash":"0x23f0022b1387646eb6e2ef07997b84e9dd7fbfcb38d7667d31a8430b60ce8c29"},{"blockHash":"0xafe0b6aec651d567d007e70506be2f2f09035d3c3933692866395048170cb4e3","block":9942877,"r":"0xc2bc16bcbb793496d9ed69d458ddd2a33c6fbe5ae7eab7f114e0c443ac50192c","s":"0x44ed69b0b4633e6d08f99fcb86bf34800fd515dd11e3f770f4c7fe5a4b114cf0","v":28,"msgHash":"0x23f0022b1387646eb6e2ef07997b84e9dd7fbfcb38d7667d31a8430b60ce8c29"}],"accounts":{"0x3589d05a1ec4Af9f65b0E5554e645707775Ee43C":{"address":"0x3589d05a1ec4af9f65b0e5554e645707775ee43c","accountProof":["0xf90211a01bc80df3a0094d2b055b6a608110e1ba2277c05ac3b92c520c00247d3cb9ee31a0c0eca032a9cb32e65c713f20915d8873cb3123fab3958c7844856feea95d99d9a047a86a13f282327d8cc4e13496526bf7d742ab9fa1f545e46d73155b671624f6a08bb94fc6e87dd9115893371f94188abd4c3795db74885852feadd1b6cf13cb5fa0c842570576bf6a86f43471e73ff89a3fd4fef382c49abec69a0a77db28c4d48ca0f5e7f0ea98bd415bf25c17dec80fa8952f658ec60ef7deb372e099f1da7e228ea0e60628ccf204613ae8d64ae8823ce82eb1b7a63154c9a3c1d1a0743e11edccd1a08d73630ac83667b34b574c9acdc2fe7fd60683906f2c387f9983b583d97f659da0dd9e2eee19aec1333f2dc3214a06785afc15b08840b2cfb0e3657eb6bda7c749a0cb2781796513576b248abc27f1c04eea1ecdda399ca8c909a6927677472277cfa0b3b57623a8e0d55036d3a4387f7cb62e9a8931c1e1f529aad0af90fda1c33a83a0e6d8f7861b2ab4a42ed59a6475a958408a4a394eaf4957c5b38441423e0554a1a0f55fc52ef09a2bfaa7d58d290830836db2e43bae41932dbed56752321367dc48a01417b8fc48b8a33eb0d1cae96f369992f7ea9adb4021ac294d02143aa2232de2a00c6a98c4522a378c3ec6f6b18d1f8926b7dc41f7eb3cb15a99e9488dfc29336aa05dec2c276b156ba75434f96cb14e668304adfcac90c26477fef367956c9b725480","0xf90211a0c4b1cdfe7bea9984a8ec6706fb50f7c43463776336e5ba21f61c73b1d9acfe46a0514f8822385f364efa68303d5145212bbe87383195bda415389024939b6bec42a02938cc2dec6e24f956583c40dfb04b9ede41b6a62ba880da08452dbfaa894079a0a0babc5e9721a24b28a19d0682d00dad7aafd682829a038a2a20c74d6bcbd52ba0fc1d673d6fe18f1fdfea4b4070bb416be3fba7a78cb22f891b736bc856d82147a039ce06cf9541c284bea43ba3a792780a6f49cd82bd3aa4a88ab636a1d20e9751a0467ad7205855f4dfed9781dff438249557abb41d65e79cbbaaa1963d051be522a02979567b9184d60816ca9741cf7bdbe7fe1871740a7880be45ed7cfd2a11212ea0aeddde59deede4a24b4003c0bced269753614801c76eb11626ccbc9891e3aadda009cabaa42e67882970bb5fbfff5f737a7cc825241e27718c94a108ec3dbaf661a0f27fe978ea43a612a30ac8075f5b9fce2a5afaa7469106b94c939e9a4faf034ba04e6d03f2e631213f31df7cdae03d65dea6bb79c31f2034a3bd89f60314f6d564a09f274d46fcbc3683169a7a344d655526958114befd001e7c6282e1eb23406478a06751de224e61f2a72b0488622c967747a33c1479fb86e2dcb8ff9ecbf95f562ea072d408c98c643d6c79a8d4a0655622f108825187548158b888fcdbd3a058cbaba0e2048c3c29e787a92415f0cefe6c40fbd6485cf74e3d5191dec311f823f371e980","0xf90211a034ca3b025d7da3d5923413b18c793f2e08e454adc564501e1d6aba388c078090a003d36abf7714d3d5d6c0d28c147f3e30cf7edc4699605920cfb8fe5bad322a53a0a4cd3c50f8760bd999441cca1dfd495ed0e6d6f5e5b593d3f959accbcf432f31a008beab2a9f22abf4d11892919300ba515cdd03526802c0d385e6be9f7b8c181fa01d10fa37863bb95c7f7b8aef77b82e98135166bd8f89dce579d784be0f2facd2a0a0d9e30e66236eb9e7ea014b643f45013c03447895f2050eabea32342ed907eba01d9462949cae395f7907b9f15edf37e09ac8338edf64fded24bbaced9ca94fb0a0ca5bcb84fa3a0717edf8d038c9cf178c96556eb4f562a8c914e8883dc6260922a04e089b0f635e0b80dcf7c94a061c60d910386c675ba1b03a589e3fa98eb792d1a0f8e86a0b6e9ddfb59f66dd3ceb34e2f62f36dce58352d8d59aec9e6d7c49607ca019faa08bea33339aa4cf83c6e526f0f57a22cb8661b3cd086677f02a185f1840a088b22c9d3c8fc67aded6634c10530c3bcbb538a846679ae8e98de352ec075378a017b35e80ec6e3dfe87ded07ca2467fd7af212f843aa66e9660f5906bef594bb9a0eac5bd3e0216672bec1ed7b8493df20a7f7853abc844864a7dfcc066bac88038a05c9b354884fd48226411bffaf6565c933aa0981db76cc4d7e3da99ea1ce54a44a027fe4950c735112b730e114d2e364117f297500549c6ee32186760ef23855a7780","0xf90211a08f281b5dd8eb5895c18b01cec29f2e83f9e83bcd7bc1dd9b5180a9e2bdd6d0d0a04016cf85174803216549c8094cf0cf0bf2245d625096b9db96e82df695880d50a0ad45420597c83f192f87249f91b19890293851f822e34651413b44574e17e3f8a0604f8cdfe442000a1842a445c8b1cabe05a727b5a6fe45d377fb6ffef5d5f856a07445292294c011ab0f42261a42d87af97b450e0351e80ff56cd815f2d5d1e1f1a0af22355d7b3c535eb85aa19ace1b9bf489cb54427cb8ff2f5a1e78901ab35374a0f9a3bfc6d12a77273e86d482add969d7f347cb1b314be903e3baa1e11b563fe9a03cd15f3e2371319adc6868770c2c10518c422a4ef3b5fb5bafc427d3b1ebaa9ba0777339b505aedacba26041ff80d004442c269625a997c2473a91984e1b94d171a0b0849536327ee811c4f95c921336f413a713023320cca724e72ba9882376e5f6a092e117545a8a2d0efd86b00c4af76a0017bc717df5f4b5b82f97991c8e615051a0bb80bd718e06c263dcb507d918f5b63e8eb2ebe16110d81746338bac073b02cfa0b7429c71cf26ad3015327c1a7fd7fdb0109b20f1e4f9ed6522d55127c63ab72ba0ee2ed288777f4e34219fb39cb1427038eaf9b0ebc1bc3100d3bc608ad559962da0a38227c0923c22436d6b09e3b2c2f987e9767a41eb499d6ecd7c54fb65de0056a0fb3d8c2483f630eb98e1b8d704c737607ecc4a886b146e8c4f1e1e5d2cb0bba880","0xf90211a0007182926b4590d18e134ccb1ea3a401aaa47e7eff4fd1d6bc2f9b6434ed93d6a08f982db1a221352e63bb521017723d293e4845ea41260c8c8d996b624fd826d1a0ead706c1b56c1a4186c1fd59bca2099fc810dad349f6c7936e7331b0d44bd5b1a0655e9409528992f670675b1fff90a531edbfc23cf56ddc5f025e82b81477702fa00f560d05bd6b8e4fc1ce27d099e1b44c7539f9d6fe060b17b52e7e17b496d905a0623690d5b53a34f9393754ce943690fd8d7053f773446a5b597f2109fafe5694a08f13e5039f3ee69fe5bff01e9cbfe6f206ee2f1bb619e77de7a6211c8d6168d9a0740b587c48996139f6a4fd6a240d420fe8e5e8a29881df206c3ebef30a53e52ca02c8ce1d919a2011a518a1a12adf2f3ad247bcd86a5d06ec2d446ed51109bbe99a002e4f1e237a470e2334518d9eb799ee65beb5967eb0d306d13484dbcb4f5debca038908f001c76778a829ddaf4de9348712608e7cd9079d797e7c3200dfd8f9912a038d3c1f56e2db2731fb5729d67f773c323c80f63aa4fa5106f7fdad35195762fa06b748e2d4949944434cb96ac8cc88f49f3b56777297afc51d5b107e3cbd7fecaa08dfb7af7a8c5917633a6f262f846322acf8a0f49dde7f47256875805e1334cdba00d576923cf134651ac7f03748a389f910095f7bac41342fdff30727199a404a8a0329011918cb81603381901b80c8db33b8efa955747b9ebc5186c6e73b59cdb2680","0xf90211a0d47d6184bdeff1febf91a62a76f365ba93a3ff4304a7444667d8262484ee629ea079aeae6ed289fdb1a1e09c9914b8a92102ee6745914eec3b56db5f3917b6bf81a0c087b90751815f64e9cbeb5a806ad5a74cd4ea5eb10947ac3f49f54c189d74b8a0790990288ec553f53a7d2caecc944d9c48df92ccd857e47cc697331c3319d3d2a0e107802e6a2c31cded0bf9438cbf45858df71b60f0fd06557267057664e0a7aea005e762a515428c997b16d43492fdc57176a30afc3ff697efc771e21175eadfe4a066c7958efbb4aecebc9f6abc2b8d18d201dda4492d256fe1db70e4883ab0a4d0a06a403497249fa31033cf372fe29e7a29a9b2085f295e79572e4b421361f9099fa00a4a8d1f52b8ed4c45f918cd5cdf6bde86e1df27d79184e89832d53e3841409fa083d9c8977e9375a37f81bf610ba1c7f97027593b7b71885b0ab9adfc258030faa072053a3b155e8aa7f034cc51f8df9191afcbdcc82fb64653803995fa861145d6a09188a72efe14faf8e761bacedd99e3de53cffe638d75e420b188c2114ec7dcd6a076a6c9dbd2f4292905067373cd348ea628b304c53494df8b000c765e022bb8f5a0914c5dfa4be1328a8b96e91dbc94c0e200958b63e2b2a53bf62487bcddaac452a02e8f13e9b38a7ce92a2e790e39b396e1f3d601a5c7de109ea02904ac3aa53bbaa0d547fb9a880c755e69b60dbc76a4efce8d5b51c084671933346886120651664680","0xf891a0a01ffcfeabecebe7aa09ad5a5934dc6b371dbe9bbd60314d3f201c7efc75e9bb80808080808080a0883e83f5d04310037e79772390a0ce4a1b6f1da38dcca877bb7cef16fad4cfeaa037684c97990b2573ba731090624a22ad1b32fea2311ca13f35f8df4980d2fec28080a0c1acd997e1c04e8211326fb1e6f0790069682924388c8892b7a4df4f06fbd03080808080","0xf86d9d3d3014a61a4de5fa48f87672539d42e0b70c32dbff933fbd6a8de3d269b84df84b8087470de4df820000a0e989bdd1768eb738801e6fb19908fdb6dc2c9246314a6d041d78e07b8e78105ba0e3109e6ac224a3309505eb25f2430ee7a8c5274dd2eb2621b2bdfed04f64cfa6"],"balance":"0x470de4df820000","codeHash":"0xe3109e6ac224a3309505eb25f2430ee7a8c5274dd2eb2621b2bdfed04f64cfa6","nonce":"0x0","storageHash":"0xe989bdd1768eb738801e6fb19908fdb6dc2c9246314a6d041d78e07b8e78105b","storageProof":[{"key":"0x1","value":"0x647261676f","proof":["0xf90211a029b4a3af658eb0efc556a31929d5e36dc0bb710a82e9dc029897aa17a0557aa8a0f7d84e63ae159d0b023c5223093b0f5912ee210bc0036a17db101ccd6be1db0da0a2a3c93da0ac6d2f44d0c480317bfcba42794e8dcb4361b6ac38f077e413a412a03bd352908e67268c18396524fdbd0a8fd4788357bc8d9dca174dda3297670aada0abe2ee08e2a891e900fd5b879fcffe136b965a1d12aa43d9e04a52c63d749eb6a0e5ab899c1f0ec07570706879ef3718f36f529e3187c9dd5a7b54c15d6bcb46f0a091eb18da559060768b395f6cb43b7cc2415eea36644333ba3cd242f8f6ad9907a0e9498fe4d4396a313dd662a4c8ef6a31db855b8ee83ed6d9d131360e09b10565a0b967576041a0547428ee5bede6e175e5bb79bbcd5134a11c94d1c791b229f930a0fb800fa73c797beaa5b650779e4890cc12ca4797fdf8136f57404f9414bc5a0da0b48bb1d760377df055e4651eaa4bc0d040e55d471c1651f6a729825544502861a0f90ac3838d934fb34b7c3ba52b3eeebe3afa84c5d9986d2625ac6134fb346155a0bf90a96c2664779d2001e01f5286a0b2b9285e8b6706f847a8c7a67d7ab1410ea0881a4782b2e4bab0564e7da59112639ea61e7eb31878062ed83c6efc97d10541a0399700f99d0134f1bd20c6b8f3ebc5d49d009e5fc6e0cea4db4352ba091cb1c2a0c3dae36a5cb1dfa08442851a429e591c33ca2153e9d382959d7748ee25efd04e80","0xf90211a0d6e8ded376a1be485b0de7a374c6401f5f0de21b1591c1c9f7cf8723e91514dca0ccaf020226af05aaedddacd9805d0a4be3a0453d27e1b64690fe52ab833f744ea07d40f2848ebb171515f0dcd44ffd3f2f1bb98dda59ac48ec4512c7c2eee3dea3a04438c80fa0a1812bd390d54860fbbc27a6b6aa66c7fbfd063889c56df88b10e9a0dcccc6d52dee872c0abd338a031a28bbeb06c383690277cd202c025b83b86650a026a2ef003b0cfbfb4f255a9b907a3be0735881483d64c341615f99a51b334995a0ec5a40b81417b37ed3204100fd89d34eedcaee20bda8eb4b52aee86890fa593ea0c94e6703dcfc1becd678c27c6a69d80743f6e5a3bdfb1b44e6db0380b195ea90a0fc631a0ebf3369be017448157741b4be587d8c8351fdeb5ad7f58c5c5db40997a0df3e34997b008367cccb92e5e4f552bfa3a20b8ae2c4855f0cd2b35d89d3f610a0003b67928ae75c471228e00ea08c6d13cb58e85e1f4d2a08f14147d2599c6118a003a9703ebbaa7b0019ad53adbe9fe8876e5e34491cb1ce8eb4dc4be0bbef9e6da007ad8c53c90aefc7ee41721906ccccf37a10cd44bfd0f2afc85be14f98a56fc7a0d54407aeee4d5a86b1dd77ef3b53977b3666d3dcce25251f0b68405364e10c3fa03777c41cb114d89cc2c79da5961d75bae725ba26f8de4c81d1aa389512f68202a0990e3f564a54d81a6566b183fd9cb903604fc47f57ce0636f23ba8b8211731bb80","0xf90211a0e2071008b4a6b8464b16dd6a23b002d215ba7d0fd8f03c70aba6083326210c91a07db52b5d5b900f74ae5e586541ef44a9d5202369f30d557d2f0c74278146fcf1a082da179d66c0b9c82137826dede382a980a8287fadc0f5c44c6a4eee80e04d00a01c665c3d29081f96eca2d59e8560e776b532fbe8e4617df6a55a53b8bea7db6ba08f909e1c029ddb1e964972ecd177d7c351c716bb3905d0bfb824e29372925056a0413d7f189851ead56c8815557b5564311144b5532b7ee8d3906bd05084b2abc8a06db285d42c936baf248c570438078720e212a58880fc32af1939f73d9f4f3be8a072ef28f18df14e105f437ae729c03163abff7258f93f2da04c3a6506874900e5a0d1c826596075a14f17a9ec56519859e4bfa3ba148d62ad428c5a069d451adc2da0313d20f5023536cdde966be00cfe520562dd2c5241c79cf4595ab142cde36344a0719673d3750afb5cae532ff0eb1cf65375febff25c1b6b8fb3400c941c2d2b18a00e5d86563abcbe40b224709b5e90bffb10d87f67637fca08d4b0a004cb3f2e18a041517fd55084fc1d3f1872b491e530eaaf0a4e27bf4945972100ea4613412791a0b7bbda5a58d75fd3f173cdcb44e5e50e89f7652ce2ae3f41293604a3d35c9e87a0a50f14c2520828c7235b265209ca51bd092660fe3a617be6e6860a3522adb42ba069d7c6c0966908e98ea06923ef46650a663285a27c5539f4c5ea32a72f643af680","0xf901918080a0e4875a9d7ec19d0e3d2f527c9953c0bfd25a6ee1663be1708dee1861262fa817a0849f426b7750cefec28c6cc38b77ffa81f862df92e66bb3f8a7c95b578ad3bd0a03c0ca87f1693f79c583326242f6c70165b60b6401a43002bf50b6a3f3f7c38b680a06a22837d0858908e5375abad8b0c264f68198168edf2bfdda4928709308244d6a0cf07517f36125e487d0bdc59e62829dba9da9cba5c0332b6623aa4246d1d67cda0e5fbffd11aa079a54845f2b05c4d798d5902bb4e11de6e700140c03846375975a0a883e0f364abce1f8f82bf84e5455b0485ecdc121686f944b2419c35a3e61deda01e39630ea86ce6d921585715b03c63e1ccfe7b5751c585ed618f4d270cd286eca0f312d660d08ce45a52918af8496d71ff9529338e107e6704da9b5e8446c0813d80a0a8f81547227a6e72ba1afb9a0a9a23c24a1c806c968aa09ab14cc23d6bbcf7dda07e94bfda83c8058c2dd176a52d7c29515eb681f988eb228a34275095c5fd42a3a00865cba21bd63c2c0fd860ec733cf1a5f33b7fcc56676e94bdef028a9b73c36780","0xe79f202d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf68685647261676f"]}]}}},"version":"2.1.0","currentBlock":9942883,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":244,"rpcTime":163,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x647261676f","in3":{"proof":{"type":"accountProof","block":"0xf90215a0afe0b6aec651d567d007e70506be2f2f09035d3c3933692866395048170cb4e3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca03908f6a6022d837d83857c88b66ef66d25cb8eb0a15d36ba99845ba257c2f0d7a0d2911eda6dfebe0ffd4d2e47a6c8f2575e774988646fb8bfa146ad05ab5d656da0e0853c6608dd3b53b9ba6067f3c53ec69a6e95a89205c16947144be8afce9741b90100a0ca1090920320480888138ae2040d455084b8830e98047c2841506510294c08168c45c129083a162301100083142548120084430923060530ebd41012ad280c44e120d0863146123e82d369278e66456000b81500053024081a93858290707a72e09107020041128d6a411400200b159c40d254ac5c1000080c467820ad521ae033c5f34284a0024418465d86409ed530000f5101d8305a10d01a00077024f49614a1b300c030017e086092911b8a112811fa288058192d66016ac59209a24102dcc73309020509e179e674001081112c515b4801598004088138181cf9617880f13d3c31041059c040009c400872442440215c761048c0c0b9b215c8c568e88707d8c478f6e7738397b75e8397e5b683975944845ea46e7894737061726b706f6f6c2d6574682d636e2d687a32a0494be2be5252b3115169a9baa7603cbf72e005268fd7cfbb0621d8e20cada2f588c4165af40347d2a9","signatures":[{"blockHash":"0x3f78251bdd900b549bc9b08b07926452eaa3abaf9d807ae58bf074e20780791d","block":9942878,"r":"0xb05cfff9de0a631727d6ef0e62e9cfb1e8bf861d8c6557c86e6b402a592692a5","s":"0x33c0d9fa8fc53ec21c3e9bdf23d07473e58b978d46ef3719211ab1e78411a536","v":27,"msgHash":"0x21d449823825f890813c3dd6746f92e13a1a9a0e13d1aef880c24ac08627533a"},{"blockHash":"0x3f78251bdd900b549bc9b08b07926452eaa3abaf9d807ae58bf074e20780791d","block":9942878,"r":"0xee6696709967b6cd46abd3ca3d81a2b6d2aa1252f45176a44153f1d3dd00564e","s":"0x6f2c7da12183db1079d58d8bfb644a48730ee75d7a71329eaacf8d86ec08e891","v":28,"msgHash":"0x21d449823825f890813c3dd6746f92e13a1a9a0e13d1aef880c24ac08627533a"}],"accounts":{"0x3589d05a1ec4Af9f65b0E5554e645707775Ee43C":{"accountProof":["0xf90211a08c78de803e9794a1ee80285f4aee861f843827de26a7511319f08b85d4177d81a06294467827bad87a521db09995859cb248f676ec50bc1c44c4422f9f9204b794a0f3a43f5f3c3f1fe78440906fadc226fd3c80f4a52ff855f2ed7bf7f9201bc04aa026c122fcfb3d2e2e6873e06b6f4b2c812611cb1f416804edfda941cd729b59eaa0bf7de4bff43af1c01eb4e46ffeb51617bdbdf76586977d547ace30c262a6c95ea0fc5cff51b73e8f72b7e726b30f9b97758a3a1d1bbb83bd400a84d3b4100101b8a04ceb8d8fcc2f606e0c09b603f79def62b7effa7a5ede85418f2e7f4d4dc67f50a05371fcada83eb9510566c9123db22a5428484bc3d439042933d1bf14e159c57ba0e1513a56ea7f339a3d4cd259b4e3eb5d1fda876e31ebe381c396dfe2d7b67838a0c551b50a618859d257c7e6192986531c7490f0a02f1ef5a015da828de8a8fb8da0d41af101a9dfa7fccf966548dbb274d7478732c4a6a176299a8d136435d5d427a0207fd03ac8e9e7d0a2a7d6fb53909b228af34e3e8c1e10260e18f9b16d9754c7a031a885d1bd113522ed16031d90b9162f90bc5311675d65f7788f4735608a3793a059260e8dcc759a4fd22b0d1fb3be0c701f1d0aee3dbf91a361470aafadcdf469a0d927b9077dcdcec0e37153e345f4450347a6a733a9132f934f53d866a0e158b7a00f6dd37e336bf646a3d75479054dc29d48ed78a899f05e35a857ee796461300280","0xf90211a0776a8d7063986191cfe6005407b805d5e2c402c5a0030841a41b71ec55dad8e2a0514f8822385f364efa68303d5145212bbe87383195bda415389024939b6bec42a02938cc2dec6e24f956583c40dfb04b9ede41b6a62ba880da08452dbfaa894079a09185f15fd4daa6f937ed3b4cd0a64c3f577ad93d2b0602900745e2cc2e5da564a0fc1d673d6fe18f1fdfea4b4070bb416be3fba7a78cb22f891b736bc856d82147a039ce06cf9541c284bea43ba3a792780a6f49cd82bd3aa4a88ab636a1d20e9751a02847787e55934eacf122d56905b2989b890afd1dce030cf01b110d0da5a1ca4ea09404cd8529663115f9c1a863ca949f142f2ec8610ad859a8ecf4c21cc31dcc2da01dc57614d63e87f0c472940b65947e4fbe29d12fb6e468def30308b9d34afe3ea0ffe0d24b1a37f4cf4c00e3138ed80e45a933c09629994b995bcf8244e65651e2a097216a5f24b67e8fa576e055aa686b715e4246bfed3ddaeebb6d0fcead2a4ecba0c6c6902de2192300ca60b452c1354d2e338508fdc34e2a40451ce0e448fe6d49a09f274d46fcbc3683169a7a344d655526958114befd001e7c6282e1eb23406478a0556afc1a243c717e2ef27e5e29d01a696c0a96fa60ae184e98cc770fa927686ca072d408c98c643d6c79a8d4a0655622f108825187548158b888fcdbd3a058cbaba0e2048c3c29e787a92415f0cefe6c40fbd6485cf74e3d5191dec311f823f371e980","0xf90211a030bee018262eb0f20d731eaba4279e94abe092f4069cec096bafef2bd83782faa003d36abf7714d3d5d6c0d28c147f3e30cf7edc4699605920cfb8fe5bad322a53a0a4cd3c50f8760bd999441cca1dfd495ed0e6d6f5e5b593d3f959accbcf432f31a008beab2a9f22abf4d11892919300ba515cdd03526802c0d385e6be9f7b8c181fa01d10fa37863bb95c7f7b8aef77b82e98135166bd8f89dce579d784be0f2facd2a0a0d9e30e66236eb9e7ea014b643f45013c03447895f2050eabea32342ed907eba01d9462949cae395f7907b9f15edf37e09ac8338edf64fded24bbaced9ca94fb0a0ca5bcb84fa3a0717edf8d038c9cf178c96556eb4f562a8c914e8883dc6260922a04e089b0f635e0b80dcf7c94a061c60d910386c675ba1b03a589e3fa98eb792d1a0f8e86a0b6e9ddfb59f66dd3ceb34e2f62f36dce58352d8d59aec9e6d7c49607ca019faa08bea33339aa4cf83c6e526f0f57a22cb8661b3cd086677f02a185f1840a088b22c9d3c8fc67aded6634c10530c3bcbb538a846679ae8e98de352ec075378a017b35e80ec6e3dfe87ded07ca2467fd7af212f843aa66e9660f5906bef594bb9a0eac5bd3e0216672bec1ed7b8493df20a7f7853abc844864a7dfcc066bac88038a05c9b354884fd48226411bffaf6565c933aa0981db76cc4d7e3da99ea1ce54a44a027fe4950c735112b730e114d2e364117f297500549c6ee32186760ef23855a7780","0xf90211a08f281b5dd8eb5895c18b01cec29f2e83f9e83bcd7bc1dd9b5180a9e2bdd6d0d0a04016cf85174803216549c8094cf0cf0bf2245d625096b9db96e82df695880d50a0ad45420597c83f192f87249f91b19890293851f822e34651413b44574e17e3f8a0604f8cdfe442000a1842a445c8b1cabe05a727b5a6fe45d377fb6ffef5d5f856a07445292294c011ab0f42261a42d87af97b450e0351e80ff56cd815f2d5d1e1f1a0af22355d7b3c535eb85aa19ace1b9bf489cb54427cb8ff2f5a1e78901ab35374a0f9a3bfc6d12a77273e86d482add969d7f347cb1b314be903e3baa1e11b563fe9a03cd15f3e2371319adc6868770c2c10518c422a4ef3b5fb5bafc427d3b1ebaa9ba0777339b505aedacba26041ff80d004442c269625a997c2473a91984e1b94d171a0b0849536327ee811c4f95c921336f413a713023320cca724e72ba9882376e5f6a092e117545a8a2d0efd86b00c4af76a0017bc717df5f4b5b82f97991c8e615051a0bb80bd718e06c263dcb507d918f5b63e8eb2ebe16110d81746338bac073b02cfa0b7429c71cf26ad3015327c1a7fd7fdb0109b20f1e4f9ed6522d55127c63ab72ba0ee2ed288777f4e34219fb39cb1427038eaf9b0ebc1bc3100d3bc608ad559962da0a38227c0923c22436d6b09e3b2c2f987e9767a41eb499d6ecd7c54fb65de0056a0fb3d8c2483f630eb98e1b8d704c737607ecc4a886b146e8c4f1e1e5d2cb0bba880","0xf90211a0007182926b4590d18e134ccb1ea3a401aaa47e7eff4fd1d6bc2f9b6434ed93d6a08f982db1a221352e63bb521017723d293e4845ea41260c8c8d996b624fd826d1a0ead706c1b56c1a4186c1fd59bca2099fc810dad349f6c7936e7331b0d44bd5b1a0655e9409528992f670675b1fff90a531edbfc23cf56ddc5f025e82b81477702fa00f560d05bd6b8e4fc1ce27d099e1b44c7539f9d6fe060b17b52e7e17b496d905a0623690d5b53a34f9393754ce943690fd8d7053f773446a5b597f2109fafe5694a08f13e5039f3ee69fe5bff01e9cbfe6f206ee2f1bb619e77de7a6211c8d6168d9a0740b587c48996139f6a4fd6a240d420fe8e5e8a29881df206c3ebef30a53e52ca02c8ce1d919a2011a518a1a12adf2f3ad247bcd86a5d06ec2d446ed51109bbe99a002e4f1e237a470e2334518d9eb799ee65beb5967eb0d306d13484dbcb4f5debca038908f001c76778a829ddaf4de9348712608e7cd9079d797e7c3200dfd8f9912a038d3c1f56e2db2731fb5729d67f773c323c80f63aa4fa5106f7fdad35195762fa06b748e2d4949944434cb96ac8cc88f49f3b56777297afc51d5b107e3cbd7fecaa08dfb7af7a8c5917633a6f262f846322acf8a0f49dde7f47256875805e1334cdba00d576923cf134651ac7f03748a389f910095f7bac41342fdff30727199a404a8a0329011918cb81603381901b80c8db33b8efa955747b9ebc5186c6e73b59cdb2680","0xf90211a0d47d6184bdeff1febf91a62a76f365ba93a3ff4304a7444667d8262484ee629ea079aeae6ed289fdb1a1e09c9914b8a92102ee6745914eec3b56db5f3917b6bf81a0c087b90751815f64e9cbeb5a806ad5a74cd4ea5eb10947ac3f49f54c189d74b8a0790990288ec553f53a7d2caecc944d9c48df92ccd857e47cc697331c3319d3d2a0e107802e6a2c31cded0bf9438cbf45858df71b60f0fd06557267057664e0a7aea005e762a515428c997b16d43492fdc57176a30afc3ff697efc771e21175eadfe4a066c7958efbb4aecebc9f6abc2b8d18d201dda4492d256fe1db70e4883ab0a4d0a06a403497249fa31033cf372fe29e7a29a9b2085f295e79572e4b421361f9099fa00a4a8d1f52b8ed4c45f918cd5cdf6bde86e1df27d79184e89832d53e3841409fa083d9c8977e9375a37f81bf610ba1c7f97027593b7b71885b0ab9adfc258030faa072053a3b155e8aa7f034cc51f8df9191afcbdcc82fb64653803995fa861145d6a09188a72efe14faf8e761bacedd99e3de53cffe638d75e420b188c2114ec7dcd6a076a6c9dbd2f4292905067373cd348ea628b304c53494df8b000c765e022bb8f5a0914c5dfa4be1328a8b96e91dbc94c0e200958b63e2b2a53bf62487bcddaac452a02e8f13e9b38a7ce92a2e790e39b396e1f3d601a5c7de109ea02904ac3aa53bbaa0d547fb9a880c755e69b60dbc76a4efce8d5b51c084671933346886120651664680","0xf891a0a01ffcfeabecebe7aa09ad5a5934dc6b371dbe9bbd60314d3f201c7efc75e9bb80808080808080a0883e83f5d04310037e79772390a0ce4a1b6f1da38dcca877bb7cef16fad4cfeaa037684c97990b2573ba731090624a22ad1b32fea2311ca13f35f8df4980d2fec28080a0c1acd997e1c04e8211326fb1e6f0790069682924388c8892b7a4df4f06fbd03080808080","0xf86d9d3d3014a61a4de5fa48f87672539d42e0b70c32dbff933fbd6a8de3d269b84df84b8087470de4df820000a0e989bdd1768eb738801e6fb19908fdb6dc2c9246314a6d041d78e07b8e78105ba0e3109e6ac224a3309505eb25f2430ee7a8c5274dd2eb2621b2bdfed04f64cfa6"],"address":"0x3589d05a1ec4af9f65b0e5554e645707775ee43c","balance":"0x470de4df820000","codeHash":"0xe3109e6ac224a3309505eb25f2430ee7a8c5274dd2eb2621b2bdfed04f64cfa6","nonce":"0x0","storageHash":"0xe989bdd1768eb738801e6fb19908fdb6dc2c9246314a6d041d78e07b8e78105b","storageProof":[{"key":"0x1","proof":["0xf90211a029b4a3af658eb0efc556a31929d5e36dc0bb710a82e9dc029897aa17a0557aa8a0f7d84e63ae159d0b023c5223093b0f5912ee210bc0036a17db101ccd6be1db0da0a2a3c93da0ac6d2f44d0c480317bfcba42794e8dcb4361b6ac38f077e413a412a03bd352908e67268c18396524fdbd0a8fd4788357bc8d9dca174dda3297670aada0abe2ee08e2a891e900fd5b879fcffe136b965a1d12aa43d9e04a52c63d749eb6a0e5ab899c1f0ec07570706879ef3718f36f529e3187c9dd5a7b54c15d6bcb46f0a091eb18da559060768b395f6cb43b7cc2415eea36644333ba3cd242f8f6ad9907a0e9498fe4d4396a313dd662a4c8ef6a31db855b8ee83ed6d9d131360e09b10565a0b967576041a0547428ee5bede6e175e5bb79bbcd5134a11c94d1c791b229f930a0fb800fa73c797beaa5b650779e4890cc12ca4797fdf8136f57404f9414bc5a0da0b48bb1d760377df055e4651eaa4bc0d040e55d471c1651f6a729825544502861a0f90ac3838d934fb34b7c3ba52b3eeebe3afa84c5d9986d2625ac6134fb346155a0bf90a96c2664779d2001e01f5286a0b2b9285e8b6706f847a8c7a67d7ab1410ea0881a4782b2e4bab0564e7da59112639ea61e7eb31878062ed83c6efc97d10541a0399700f99d0134f1bd20c6b8f3ebc5d49d009e5fc6e0cea4db4352ba091cb1c2a0c3dae36a5cb1dfa08442851a429e591c33ca2153e9d382959d7748ee25efd04e80","0xf90211a0d6e8ded376a1be485b0de7a374c6401f5f0de21b1591c1c9f7cf8723e91514dca0ccaf020226af05aaedddacd9805d0a4be3a0453d27e1b64690fe52ab833f744ea07d40f2848ebb171515f0dcd44ffd3f2f1bb98dda59ac48ec4512c7c2eee3dea3a04438c80fa0a1812bd390d54860fbbc27a6b6aa66c7fbfd063889c56df88b10e9a0dcccc6d52dee872c0abd338a031a28bbeb06c383690277cd202c025b83b86650a026a2ef003b0cfbfb4f255a9b907a3be0735881483d64c341615f99a51b334995a0ec5a40b81417b37ed3204100fd89d34eedcaee20bda8eb4b52aee86890fa593ea0c94e6703dcfc1becd678c27c6a69d80743f6e5a3bdfb1b44e6db0380b195ea90a0fc631a0ebf3369be017448157741b4be587d8c8351fdeb5ad7f58c5c5db40997a0df3e34997b008367cccb92e5e4f552bfa3a20b8ae2c4855f0cd2b35d89d3f610a0003b67928ae75c471228e00ea08c6d13cb58e85e1f4d2a08f14147d2599c6118a003a9703ebbaa7b0019ad53adbe9fe8876e5e34491cb1ce8eb4dc4be0bbef9e6da007ad8c53c90aefc7ee41721906ccccf37a10cd44bfd0f2afc85be14f98a56fc7a0d54407aeee4d5a86b1dd77ef3b53977b3666d3dcce25251f0b68405364e10c3fa03777c41cb114d89cc2c79da5961d75bae725ba26f8de4c81d1aa389512f68202a0990e3f564a54d81a6566b183fd9cb903604fc47f57ce0636f23ba8b8211731bb80","0xf90211a0e2071008b4a6b8464b16dd6a23b002d215ba7d0fd8f03c70aba6083326210c91a07db52b5d5b900f74ae5e586541ef44a9d5202369f30d557d2f0c74278146fcf1a082da179d66c0b9c82137826dede382a980a8287fadc0f5c44c6a4eee80e04d00a01c665c3d29081f96eca2d59e8560e776b532fbe8e4617df6a55a53b8bea7db6ba08f909e1c029ddb1e964972ecd177d7c351c716bb3905d0bfb824e29372925056a0413d7f189851ead56c8815557b5564311144b5532b7ee8d3906bd05084b2abc8a06db285d42c936baf248c570438078720e212a58880fc32af1939f73d9f4f3be8a072ef28f18df14e105f437ae729c03163abff7258f93f2da04c3a6506874900e5a0d1c826596075a14f17a9ec56519859e4bfa3ba148d62ad428c5a069d451adc2da0313d20f5023536cdde966be00cfe520562dd2c5241c79cf4595ab142cde36344a0719673d3750afb5cae532ff0eb1cf65375febff25c1b6b8fb3400c941c2d2b18a00e5d86563abcbe40b224709b5e90bffb10d87f67637fca08d4b0a004cb3f2e18a041517fd55084fc1d3f1872b491e530eaaf0a4e27bf4945972100ea4613412791a0b7bbda5a58d75fd3f173cdcb44e5e50e89f7652ce2ae3f41293604a3d35c9e87a0a50f14c2520828c7235b265209ca51bd092660fe3a617be6e6860a3522adb42ba069d7c6c0966908e98ea06923ef46650a663285a27c5539f4c5ea32a72f643af680","0xf901918080a0e4875a9d7ec19d0e3d2f527c9953c0bfd25a6ee1663be1708dee1861262fa817a0849f426b7750cefec28c6cc38b77ffa81f862df92e66bb3f8a7c95b578ad3bd0a03c0ca87f1693f79c583326242f6c70165b60b6401a43002bf50b6a3f3f7c38b680a06a22837d0858908e5375abad8b0c264f68198168edf2bfdda4928709308244d6a0cf07517f36125e487d0bdc59e62829dba9da9cba5c0332b6623aa4246d1d67cda0e5fbffd11aa079a54845f2b05c4d798d5902bb4e11de6e700140c03846375975a0a883e0f364abce1f8f82bf84e5455b0485ecdc121686f944b2419c35a3e61deda01e39630ea86ce6d921585715b03c63e1ccfe7b5751c585ed618f4d270cd286eca0f312d660d08ce45a52918af8496d71ff9529338e107e6704da9b5e8446c0813d80a0a8f81547227a6e72ba1afb9a0a9a23c24a1c806c968aa09ab14cc23d6bbcf7dda07e94bfda83c8058c2dd176a52d7c29515eb681f988eb228a34275095c5fd42a3a00865cba21bd63c2c0fd860ec733cf1a5f33b7fcc56676e94bdef028a9b73c36780","0xe79f202d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf68685647261676f"],"value":"0x647261676f"}]}}},"version":"2.1.0","currentBlock":9942885,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":3125,"rpcTime":3042,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x0","in3":{"proof":{"type":"accountProof","block":"0xf90259a00d9ef6d02caf622981d8a18e93fac3cf94b18dd18e9a77c8db411f0fe377d00da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0ac44373ed1f2ac64713ef278eb64c149d2852b3c6e2e8fa8baec774c2bcb5b8ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832779d1837a120080845ea47ee7b861d88301090a846765746888676f312e31332e36856c696e757800000000000000e79510d06e81564dc9c849b8e51296b1a0a1ed4699be356c55f2df8e6869a343269d4aabd88b39acd3e3e27b63830fa8d682075d572ef7324a849e095afbfeb001a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x0e362c7a3a3ea049502d8915e2d4125826dafce8953fc767ea7ae251711e2c9f","block":2587089,"r":"0x0b15f7395c8b6664886b4faa530384559d38fe7fb8085a4b907514af9f9f0f58","s":"0x49670321c5d63d22e9cf936c9790566b71deb957d3b2b2e1a1027acc18dbd9cf","v":27,"msgHash":"0x51fc5d0db4921004c451277abc31f6f400697834045425152d56b5375750a046"},{"blockHash":"0x0e362c7a3a3ea049502d8915e2d4125826dafce8953fc767ea7ae251711e2c9f","block":2587089,"r":"0x7e43e405545dcdb10b149415ae0d21b766a77ac8132f0d773875675336292a6c","s":"0x125426de61224b1c0b4cd2f733bc8725178fc92cfb15fc3494ce9a149ce32b90","v":28,"msgHash":"0x51fc5d0db4921004c451277abc31f6f400697834045425152d56b5375750a046"}],"accounts":{"0x4B1488B7a6B320d2D721406204aBc3eeAa9AD329":{"accountProof":["0xf90211a06e3884346d957ebec001e3e8e5004ca1d679d798cc7b10d615d2152e8def48e3a0d89255c3b1a1896cd312d9b1509b193e33fd2e50f2f8d096da7819a1ce721ddfa00b8cd003ef0c7c9b7ce8d7153de0abe35d0942197f6ed53182285a4e931af08ca06b306b6029e2c80425f0b3ca94829298ed0cc7198ad7f3497e3b22b4ec7fe8d2a08024340dcad0e6b89d370ab3a14009fdc6e1ed6a9b00018ed998331412daa0e1a0c802ea36b9b8fdea74badb41559f2f1137b1b647992ce794d0cf6dccb5b27cc1a016bb47179bb030e32abb0cd3367df83ae46f06fbcba9fd04c860bb5f3b12d0f0a0c65e93f18b161bd9ad08374eb846419333928a0ffcfa8bcca464953cf8665fe1a040871bad33eed9c4451197d1eba57c8989127be31343abcbca6511d273259be4a0c39bb2ae8a6ddcdd3c13873e9bf7284c663a8c51bf0d9ac1b198258a7375130ea002241c5e8f254d65475c1f89d7d760ae8874c2dffc10416f823eb9fd8cb06c57a07c1697577353cb9b4f16d1620b3932b4dbe73aac02819405308d58c2b142d447a060c5648dccc343d208d0b78f179993b0573caa12d805dd6cbdb3c4e6eee1b44ea0acdc3bb1db238a89af0ba0537f9661bd2a7bcdb674e22caaeac19ded828b086ca09dd86c5f8910a908484d9a14012a81daa3106925c05c6353c1d0c7dd5e5505a2a08e12266655c28cde510f25ac46413a1b7e35a5b8bf7f7e1cf7f3d6221c60886580","0xf90211a063b76caeb263cacb96c32ef40d398d69036406e1f0a92d315a9bc5455bc7a989a03c20dff6d42ac082b2a7755fa1a9e78e5754beab78a95ae363874a9274977a9aa021596766f3e9fea5492e16e4b7681f7114f4a82623d7679bc4ee9434b0d21374a039044dab9bcd20d341db3f0fe7ea2129f67871a41e11bc771b6244d50857abf4a0d4b9efdb79c5c203265720ba7f6cc38274fd9eed6d0840e915d8c71b04d8a12da063b6698ba35c33236f93c7191894f47ea292995fddef522fee5b4446818b62cea01d7189db18e2a0a916ed59b6cc0bd4bfac43dae78900179cd1ad90a094343a4ca0375270ffe8af9648d3d6c7c494572a6b837b74895e59dd6cdff92af523ea9153a0cf1a36a3f66cdba64ef91401f0feef77eb6c5bd06946e5aab06559a1ac0a9153a04bbcd6969cbbb83dff94fb761a0696037c96ada11cfd0d881f5994f6d4109d6aa06845b6cebc9359ae0b79f9d293fa34e84f5da618bd0018f8d14eb90d31e19311a00706989d3211bc7e3996f2d0b7d6bea642413fac7c630601abeb58ddd13a1c91a00d1640343feb90999ae0e3bff384a13205634be789ae1c4dc2264b4404d837c2a01349cd0a92714cad964f765bc5f9fe1a921954fdf45031fbed82be6a9e6351a2a00f44a9ececc859e54d9e05dcb3b983b2ac760fafc55f1ae3bcc543027e474242a0642e8399a698dde22819d1527a42acdce8d0b2ae8955424a43bba5d23beec6b880","0xf90211a0fe22406505ec2cbd09763ea31665d2e74121c9e1762b9cc4abb1ce8dd46e003ba0adb168280d48c2c14345808fea92457b789ded5cd3ad78776e832278d6e7062da02d850e90ca2e59370cf4fcb29da7b97fdbf80b2df1c98838d0960608328b2d45a0a6884134cba0ba719ef150ee56df08bb4a2b67e4972e84d86ee321e6463a359da03982a59148f8b5878300324943da13e4439cd6d14b3dcdfdcfbdc06a6c675377a00a10bdd387ae9e56e1161213cc50b5bc83edcb3ad959230a86b15952e69adca5a07b317be3fed3c9ca828846f3a73487e2876a70f36cc8dd01f29914879576f764a0722e213be5d08fe90c3dd4df9e7c02ad2607b450e2c984f87220f1fb06581580a0412f7f0c948023a6ac4830f47a64c4d3924e42aebd151fdd38b11895e94f9a07a0ef860f573b83e093249376054e40d4351f80240f543d9d080f2e42b62f55c000a0b6df6d9b26a4e425867c1cd4928ac0a7bcac3f9981e02fa4d9e65ca68aa76020a0c5fcfd24fd6ee236140f436a5a55472fa371e4f4302052208170fde0b4bf6c98a04ade415641a6f4a2ea3c1dde0a79d2f80c83f31233eb9f583d7928826d8eeac4a054ba5115130f5f3f0746d259086203a020217268c0db536608e8b704ccf9f4f6a0d64f20f19b12bc908b17b9d1d7bf3036bbcd342160601178a4138c976b4b64a6a0f0fbb026065534a882a04d485c62cb02b310fad32a9b26f8d1f63a57b162a99580","0xf901f1a031dd1151ac8172f3f8c5abc06ad4569ece89ea2dea207f1d8e45891bbfefcb97a0d25452bafeb233de810bebbcd009fd2a5e70d412aa403a0761af19dad99e3c86a05030f26f4f1ce968af4fff4454685c04cdbcf7b16c60640e35bcf8061ed0bea5a0c67034736890b87f94a43aeb9c69531a30ad7e3931aac71ee970596465f32649a0675671d5fe2effefcea87481bd12cc18c43284643f6883e88120b3c3e10e09fca0d70bc46f00909c5d48862cdaa0a416d4a7df86006b914db6e3032d2cb1624a2080a09c8ed7685dec224be677e17360b77e97c11265ad9fa58f559517d2abaec7e002a0a27e3ed7d5c56d482fd53dfd6e03417fbe5498b7059060632898eb0836dd627da0810903a686ec88dba14efa95e7973b11e8cc72249c83107e85da2c11199dcf4da062e805769fde7a8b67e33524277597aad4b8abd855e70d66449426dd7e39fdf1a010c26611588da323cab8002173b1350ca7c58ba867814c67a69dea94a8645a8aa0a8c5ec4ec8052a6455e725bafaf66b8e252f1a992373cd3b57b0d43f7acbe6d8a044027f59addc7bb4420fd840d993d4a2995d866d2eef28883797155ae35dfe60a012186930532d8e618ff4cd429ec9a1d8adf0d69d0985ea54ab8f3734637ae709a09c0542b81139e346f21287c3d1856e733d00004cfd57a9e749cc5f019f07881d80","0xf8718080808080a0d9fe530c31cd640fbaf2bdab8e5d36338f8f6b1833be7a6eabbe489f2ca90bff8080808080a08b793961b629a89132a1e572fa6b6e249c6d9c8338afb1ee8768c67ba6c737858080a09ac5f850c25f2ef86bf4a209fc3dc8195dc27b2e0eee6e4333307d3fdc2779468080","0xf85180808080808080808080a0c00d51a0f1941d1cf50190d3f38792a63e27a923c2ca99371d697bde51da5f8380808080a041b96ef7cbfd46f72aebc8dd18ff23d259bba117fa2259f303470140b7af452980","0xf8679e20ce9fd68353d737a0d199ba0c63a82fa1fb928ba7df15b6153b51f6c4adb846f8440180a06fee32fa94bbd3abb3cb7ba43e20e97a5818984ef7fdf33b2be9a3e3e827bb73a00370d116c18db61a2f90643faa12e3ae22a0b7d518ce868fe3f85e2f0d299fe5"],"address":"0x4b1488b7a6b320d2d721406204abc3eeaa9ad329","balance":"0x0","codeHash":"0x0370d116c18db61a2f90643faa12e3ae22a0b7d518ce868fe3f85e2f0d299fe5","nonce":"0x1","storageHash":"0x6fee32fa94bbd3abb3cb7ba43e20e97a5818984ef7fdf33b2be9a3e3e827bb73","storageProof":[{"key":"0x1","proof":["0xf90211a0474f8917f672d8457de102d47bcc5c8b0c6b5b336532242f1b3577775566d5dba0d0f7b1253b8b43a553af9999f7856ca79c6bbfbc3258a34d1780737bba24fde9a05dc8888f2cf2b9cb7d7eee6912a39fea09f0f2224f035c8dca6fb7e84ec7cc0ca0d27e7e5e3c992cc8b5741883dde30ee30d16e72a811dd64b68d9fb4f5f57f530a0e5341f5f63c29e092cae80c8493abb6a84a8d082ae042f7384adbfcb7c855f97a0e3dc758fe43b7a4833d9116996a5c7563afd53390d40d139503d6164fb6f4335a065a6f6e9573ed9a208a3f0e87b28a8e48cf8334d56f3072b2d2d14714cb24210a00d318eb4a29f228f850493ed125eac79d13cc23f22aab6222ee86cf2955e6b76a06c5a35dab6346a6afa2fa9fb364669205c6de2582546dbdfb3e267abee31b29ca0bae2193f1e01ef9d25990f1dc3f49c2174e233ec573d9c4ea708b86c5ff740daa0696ef5a90dadfba4d5002b170de8eea5d99f6b52101d15ed46b7c8426c91fa97a0fe9348826c01833515134f3b3a847845c05e323a3c052c8d12a4ff5a8bad52cca068f17fd61be108de5e9e87bdc929255cbd201071947f1bfbbe752da9c693c06da06d440d1503cdda9c45fc79273b266dbf8a737d2189ae9b17dc1457a4053b018da01255f358dc195e0557fc1dd6bc7a810f5fddc4e3bfa1aa4bc4d79e8456b2a8e1a0b8e9a2bf64468334cbe0ddce343de666a223f9b2e6bfb8b7c5dd389b404bb43680","0xf9011180a00160d491d95dfd9df3bce72916825c669a8a643e861959f0ff13f298c4ef79e180a077c23810041ba5b87e7db3d4129ad25ef609b4b5bbfdf7e7a75bf5368c2c6556a0c35e1f66a427a62d29a0421ce60fc3e72fb958f6ff212e627d7e9a5f482b7db6a08ed85e834ab19f78b5a9fdf1ad0201d498cb99c33096b7419b9820d31f5957bca07a5a20bb15067f2ea6dbd23eef942fa14da2c67866ef954b287056138cdc8ab880a083c01ccc72aa522b343c223a2c5c76a57e8379864d5426daa098a9e3adb617148080a02522d1d6ccd92e74eb51ac9d7f0fbad9cd9e65abc34ff1b6cfcfc6fb53a3209080a0c805e923a38f9bbac8b08002e5bb0c5ebdbb348d0ea633249c466056859de40b808080","0xf843a0209afa7cd0e2a506cd4f0996963f697def4c4e1a7ca2e2eb649b6d1217b7cba4a1a0388ea662ef2c223ec0b047d41bf3c0f362142ad5000000000000000000000028"],"value":"0x0"}]}}},"version":"2.1.0","currentBlock":2587095,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":167,"rpcTime":91,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x0","in3":{"proof":{"type":"accountProof","block":"0xf90259a0dcc75be9faf3fd289e9ed9727d756c082ad4a8e7c78694fa6a3eeb73e1f3e29fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a059f8767b3a91cce899558a266a4f8d69980f69382477b04a0ed35c13bbd28073a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832779d3837a120080845ea47f05b861f09f928e20407072796c616273206e6f64652d3020f09f928e0000000000000017a9d56b2adfccd20a6118aa4ce2be78afc359972f398cbb80c1b8ef674fa62a363c2a543223acced77086f87080552fe8fd8c98e9fd6fb58e2e909c4a800ef101a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x05ce38f0da4f4de7eb0faca5146fca100bbc16bd7aaabb507d9389f534016506","block":2587091,"r":"0x8b9819e1c4afa6e4bab201fa59f3b769f70ccf51a6a70bb5019df6a363c343cd","s":"0x7ba1356387e83ef856eef90ec4e3557ff899ab9b186e7839c7fc43e9f79188bb","v":27,"msgHash":"0x2d5d539186ec4853791f5bf814348b1dd45501db2f0fe2bf9b1c29b0a94c1cd9"},{"blockHash":"0x05ce38f0da4f4de7eb0faca5146fca100bbc16bd7aaabb507d9389f534016506","block":2587091,"r":"0x892a9ac3db2b778cc08c63402510f7a8f213a4599ec579d63223bd0e13f84890","s":"0x17fde6319da696e08ff668d9d3c3f1da081a615895361856a97983a43f663fe9","v":28,"msgHash":"0x2d5d539186ec4853791f5bf814348b1dd45501db2f0fe2bf9b1c29b0a94c1cd9"}],"accounts":{"0x4B1488B7a6B320d2D721406204aBc3eeAa9AD329":{"accountProof":["0xf90211a06e3884346d957ebec001e3e8e5004ca1d679d798cc7b10d615d2152e8def48e3a0d89255c3b1a1896cd312d9b1509b193e33fd2e50f2f8d096da7819a1ce721ddfa00b8cd003ef0c7c9b7ce8d7153de0abe35d0942197f6ed53182285a4e931af08ca0e0a8fbe1b445157aa26f74859c06ab4e237f67ab2c586cc5a20330b90e0b5f4da074522bccea4de6d75065444f4c9ff38552dc7adbfb7ce9f72c26e65c2ad154c7a0c802ea36b9b8fdea74badb41559f2f1137b1b647992ce794d0cf6dccb5b27cc1a016bb47179bb030e32abb0cd3367df83ae46f06fbcba9fd04c860bb5f3b12d0f0a0c65e93f18b161bd9ad08374eb846419333928a0ffcfa8bcca464953cf8665fe1a040871bad33eed9c4451197d1eba57c8989127be31343abcbca6511d273259be4a0e75068f63fb44688bf7859dd89c13622482f398cfc7ed55757ad94f6f0656184a02cd12d9717fc19e0950f7c46e427ce74c9be0b38441c833d9b6f49f536ec4e50a07c1697577353cb9b4f16d1620b3932b4dbe73aac02819405308d58c2b142d447a060c5648dccc343d208d0b78f179993b0573caa12d805dd6cbdb3c4e6eee1b44ea0acdc3bb1db238a89af0ba0537f9661bd2a7bcdb674e22caaeac19ded828b086ca09dd86c5f8910a908484d9a14012a81daa3106925c05c6353c1d0c7dd5e5505a2a02a180af99b32b6113b36f785f24c3690ef2e17069c340a2ef8eaa6c4e00db9ca80","0xf90211a063b76caeb263cacb96c32ef40d398d69036406e1f0a92d315a9bc5455bc7a989a03c20dff6d42ac082b2a7755fa1a9e78e5754beab78a95ae363874a9274977a9aa021596766f3e9fea5492e16e4b7681f7114f4a82623d7679bc4ee9434b0d21374a039044dab9bcd20d341db3f0fe7ea2129f67871a41e11bc771b6244d50857abf4a0d4b9efdb79c5c203265720ba7f6cc38274fd9eed6d0840e915d8c71b04d8a12da063b6698ba35c33236f93c7191894f47ea292995fddef522fee5b4446818b62cea01d7189db18e2a0a916ed59b6cc0bd4bfac43dae78900179cd1ad90a094343a4ca0375270ffe8af9648d3d6c7c494572a6b837b74895e59dd6cdff92af523ea9153a0cf1a36a3f66cdba64ef91401f0feef77eb6c5bd06946e5aab06559a1ac0a9153a04bbcd6969cbbb83dff94fb761a0696037c96ada11cfd0d881f5994f6d4109d6aa06845b6cebc9359ae0b79f9d293fa34e84f5da618bd0018f8d14eb90d31e19311a00706989d3211bc7e3996f2d0b7d6bea642413fac7c630601abeb58ddd13a1c91a00d1640343feb90999ae0e3bff384a13205634be789ae1c4dc2264b4404d837c2a01349cd0a92714cad964f765bc5f9fe1a921954fdf45031fbed82be6a9e6351a2a00f44a9ececc859e54d9e05dcb3b983b2ac760fafc55f1ae3bcc543027e474242a0642e8399a698dde22819d1527a42acdce8d0b2ae8955424a43bba5d23beec6b880","0xf90211a0fe22406505ec2cbd09763ea31665d2e74121c9e1762b9cc4abb1ce8dd46e003ba0adb168280d48c2c14345808fea92457b789ded5cd3ad78776e832278d6e7062da02d850e90ca2e59370cf4fcb29da7b97fdbf80b2df1c98838d0960608328b2d45a0a6884134cba0ba719ef150ee56df08bb4a2b67e4972e84d86ee321e6463a359da03982a59148f8b5878300324943da13e4439cd6d14b3dcdfdcfbdc06a6c675377a00a10bdd387ae9e56e1161213cc50b5bc83edcb3ad959230a86b15952e69adca5a07b317be3fed3c9ca828846f3a73487e2876a70f36cc8dd01f29914879576f764a0722e213be5d08fe90c3dd4df9e7c02ad2607b450e2c984f87220f1fb06581580a0412f7f0c948023a6ac4830f47a64c4d3924e42aebd151fdd38b11895e94f9a07a0ef860f573b83e093249376054e40d4351f80240f543d9d080f2e42b62f55c000a0b6df6d9b26a4e425867c1cd4928ac0a7bcac3f9981e02fa4d9e65ca68aa76020a0c5fcfd24fd6ee236140f436a5a55472fa371e4f4302052208170fde0b4bf6c98a04ade415641a6f4a2ea3c1dde0a79d2f80c83f31233eb9f583d7928826d8eeac4a054ba5115130f5f3f0746d259086203a020217268c0db536608e8b704ccf9f4f6a0d64f20f19b12bc908b17b9d1d7bf3036bbcd342160601178a4138c976b4b64a6a0f0fbb026065534a882a04d485c62cb02b310fad32a9b26f8d1f63a57b162a99580","0xf901f1a031dd1151ac8172f3f8c5abc06ad4569ece89ea2dea207f1d8e45891bbfefcb97a0d25452bafeb233de810bebbcd009fd2a5e70d412aa403a0761af19dad99e3c86a05030f26f4f1ce968af4fff4454685c04cdbcf7b16c60640e35bcf8061ed0bea5a0c67034736890b87f94a43aeb9c69531a30ad7e3931aac71ee970596465f32649a0675671d5fe2effefcea87481bd12cc18c43284643f6883e88120b3c3e10e09fca0d70bc46f00909c5d48862cdaa0a416d4a7df86006b914db6e3032d2cb1624a2080a09c8ed7685dec224be677e17360b77e97c11265ad9fa58f559517d2abaec7e002a0a27e3ed7d5c56d482fd53dfd6e03417fbe5498b7059060632898eb0836dd627da0810903a686ec88dba14efa95e7973b11e8cc72249c83107e85da2c11199dcf4da062e805769fde7a8b67e33524277597aad4b8abd855e70d66449426dd7e39fdf1a010c26611588da323cab8002173b1350ca7c58ba867814c67a69dea94a8645a8aa0a8c5ec4ec8052a6455e725bafaf66b8e252f1a992373cd3b57b0d43f7acbe6d8a044027f59addc7bb4420fd840d993d4a2995d866d2eef28883797155ae35dfe60a012186930532d8e618ff4cd429ec9a1d8adf0d69d0985ea54ab8f3734637ae709a09c0542b81139e346f21287c3d1856e733d00004cfd57a9e749cc5f019f07881d80","0xf8718080808080a0d9fe530c31cd640fbaf2bdab8e5d36338f8f6b1833be7a6eabbe489f2ca90bff8080808080a08b793961b629a89132a1e572fa6b6e249c6d9c8338afb1ee8768c67ba6c737858080a09ac5f850c25f2ef86bf4a209fc3dc8195dc27b2e0eee6e4333307d3fdc2779468080","0xf85180808080808080808080a0c00d51a0f1941d1cf50190d3f38792a63e27a923c2ca99371d697bde51da5f8380808080a041b96ef7cbfd46f72aebc8dd18ff23d259bba117fa2259f303470140b7af452980","0xf8679e20ce9fd68353d737a0d199ba0c63a82fa1fb928ba7df15b6153b51f6c4adb846f8440180a06fee32fa94bbd3abb3cb7ba43e20e97a5818984ef7fdf33b2be9a3e3e827bb73a00370d116c18db61a2f90643faa12e3ae22a0b7d518ce868fe3f85e2f0d299fe5"],"address":"0x4b1488b7a6b320d2d721406204abc3eeaa9ad329","balance":"0x0","codeHash":"0x0370d116c18db61a2f90643faa12e3ae22a0b7d518ce868fe3f85e2f0d299fe5","nonce":"0x1","storageHash":"0x6fee32fa94bbd3abb3cb7ba43e20e97a5818984ef7fdf33b2be9a3e3e827bb73","storageProof":[{"key":"0x1","proof":["0xf90211a0474f8917f672d8457de102d47bcc5c8b0c6b5b336532242f1b3577775566d5dba0d0f7b1253b8b43a553af9999f7856ca79c6bbfbc3258a34d1780737bba24fde9a05dc8888f2cf2b9cb7d7eee6912a39fea09f0f2224f035c8dca6fb7e84ec7cc0ca0d27e7e5e3c992cc8b5741883dde30ee30d16e72a811dd64b68d9fb4f5f57f530a0e5341f5f63c29e092cae80c8493abb6a84a8d082ae042f7384adbfcb7c855f97a0e3dc758fe43b7a4833d9116996a5c7563afd53390d40d139503d6164fb6f4335a065a6f6e9573ed9a208a3f0e87b28a8e48cf8334d56f3072b2d2d14714cb24210a00d318eb4a29f228f850493ed125eac79d13cc23f22aab6222ee86cf2955e6b76a06c5a35dab6346a6afa2fa9fb364669205c6de2582546dbdfb3e267abee31b29ca0bae2193f1e01ef9d25990f1dc3f49c2174e233ec573d9c4ea708b86c5ff740daa0696ef5a90dadfba4d5002b170de8eea5d99f6b52101d15ed46b7c8426c91fa97a0fe9348826c01833515134f3b3a847845c05e323a3c052c8d12a4ff5a8bad52cca068f17fd61be108de5e9e87bdc929255cbd201071947f1bfbbe752da9c693c06da06d440d1503cdda9c45fc79273b266dbf8a737d2189ae9b17dc1457a4053b018da01255f358dc195e0557fc1dd6bc7a810f5fddc4e3bfa1aa4bc4d79e8456b2a8e1a0b8e9a2bf64468334cbe0ddce343de666a223f9b2e6bfb8b7c5dd389b404bb43680","0xf9011180a00160d491d95dfd9df3bce72916825c669a8a643e861959f0ff13f298c4ef79e180a077c23810041ba5b87e7db3d4129ad25ef609b4b5bbfdf7e7a75bf5368c2c6556a0c35e1f66a427a62d29a0421ce60fc3e72fb958f6ff212e627d7e9a5f482b7db6a08ed85e834ab19f78b5a9fdf1ad0201d498cb99c33096b7419b9820d31f5957bca07a5a20bb15067f2ea6dbd23eef942fa14da2c67866ef954b287056138cdc8ab880a083c01ccc72aa522b343c223a2c5c76a57e8379864d5426daa098a9e3adb617148080a02522d1d6ccd92e74eb51ac9d7f0fbad9cd9e65abc34ff1b6cfcfc6fb53a3209080a0c805e923a38f9bbac8b08002e5bb0c5ebdbb348d0ea633249c466056859de40b808080","0xf843a0209afa7cd0e2a506cd4f0996963f697def4c4e1a7ca2e2eb649b6d1217b7cba4a1a0388ea662ef2c223ec0b047d41bf3c0f362142ad5000000000000000000000028"],"value":"0x0"}]}}},"version":"2.1.0","currentBlock":2587097,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":122,"rpcTime":48,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getTransactionByHash": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","blockNumber":"0x97b3b1","from":"0xba411b9e641c51c8a7962d03cde51cf077dbf836","gas":"0x5208","gasPrice":"0x1a13b8600","hash":"0xae25a4b673bd87f40ea147a5506cb2ffb38e32ec1efc372c6730a5ba50668ae3","input":"0x","nonce":"0x0","to":"0x49ab060a6c8586fb9917d4197412048f1def3d66","transactionIndex":"0x91","value":"0x1410d379b1000","v":"0x25","r":"0xbc8ee342e9cf815964cdb327d82aab1c0b4b4b586f4eb33b2e49e9f89eb6f92c","s":"0x1baec64c5d3c93eec307e68a95f4b2c7e9840295c08f714a4e283fdb7b681e3a"},"in3":{"proof":{"type":"transactionProof","block":"0xf90205a0ed24fbc45d6a1ae29c998f98da6f13fad051076dc46d5807cd443fc95045ec6aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794da466bf1ce3c69dbef918817305cf989a6353423a09194d13d1c7209a62a5114e2510b0108d4f4e215440e994784da6282ad1dc779a004815dc9dbc57a7759c29afeb604e680f6b5816d833e097d0574eb521006cfd0a04a96f6456bb3ff96ed5c2dfcd72aa8bb514cf4b56cb64b3bf12395e9ade7f22eb9010080026c1b0451323c55082d49620618c28db80a82bc92c03c90014383382a1d218305111456053972a14115a782ca0580d20881a1c9e42405215c4112d02e812c043800e086aa4511cd84a5a89c91600c1480e920c2ae204783405b19aa4c659178af02400650101a4024463800680a012e2613a91e0c21687eaa2516b1209430096ca47b0004a504828503051205b419bc104d0d4182338260c6222600b400f4971e28206940a28a0b19059e422ad952519a01739cc45000873244a10800506722882c22647110f02890f0a00a53667e20004611d09a30010226005810086a208a106ca4a1105619c26540b0c432a24464a50503881200d1682e00010881a84a8707f6d7015511aa8397b3b18397c55383977658845ea43c488473656f31a0e5de79db17555a678536dc7ff0add74c0eb3259b591b2c5dc21431146f3fccd3884993ec801d63b2b6","merkleProof":["0xf90131a089c7a904e6b1f1064d6191df016832784a66bb774d02c8b467f44b69d68e1fffa0fc35d7da7fcfbf9a1a9226d08056497a46144284f1de05aa081681cb6a303c63a00acc07cc308f665363c2059fc33f2db97500b197dbcabea45ba132fa5eef09ada06bd360cae105fbddc419302ceaa353bc50cdf0f9b7fe868a20d09ab97a42ec79a0872c3ed4ebca04f21e9eadfd92b23e9e612c4c841bc0abb4f15e1695d42f2da8a0474d57941db534fa700ece15858d51c2198322fdf64142988347950be251bb54a022bf88edf2db7698c55bab2760cd3d95082a227b965a33618d4de810563bc467a0f616c4f8bbc59e3c523eacc93b350a674ee98792004ab3c4f234d40da95da66ca0c37da06c79bcb17616612890ccee8518679feb139ce33406a9f039151b0995098080808080808080","0xf851a0c0ab4bb48998e761227dd88c350a2c0c22d388c51f07c021cf7c625adac527afa04808b89509e350f36efc3c5a9d82f59d2fe0b9f3f1ae111ec68ee4ec7f59a412808080808080808080808080808080","0xf8518080808080808080a014f9a182ac5c9ff0d852c7e22577c8ea0355ca9edfa92393e591193d3dfef1a4a04773758b019f97afae878ae175afdc14a369811db93196c1a66d4f3dc53006a580808080808080","0xf851a06ee7795aa4754a2195e3fccb03512a6a5cf4814864abcb308098b52ebb25fe3ba0f3e8a16577842f474120e92880cec5630cef6bea5bfb8322ff37ccbbe9e767b6808080808080808080808080808080","0xf87020b86df86b808501a13b86008252089449ab060a6c8586fb9917d4197412048f1def3d668701410d379b10008025a0bc8ee342e9cf815964cdb327d82aab1c0b4b4b586f4eb33b2e49e9f89eb6f92ca01baec64c5d3c93eec307e68a95f4b2c7e9840295c08f714a4e283fdb7b681e3a"],"txIndex":145,"signatures":[{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","block":9941937,"r":"0x1688f0e25148779c61a94db81c1534e7abb2c78d57fb11e34f30ae9e34ec81c4","s":"0x0412f2cd9768f02a5df98ce2a58243fea2e53f8f225e613b4178c7676e6cf198","v":27,"msgHash":"0xe36a4447ab365cf28538d2d02fc195d5b15a6a18fbf2dc0864f5a68986a53da0"},{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","block":9941937,"r":"0x3334f002c6cd9153f830bbeb45d7010596dc4cd90b2ff206757593f33e05b19a","s":"0x577c4efb08bb047d7b8774c4cd0ecdfe8041aad0225d1bfb5e004891d1e9e90a","v":28,"msgHash":"0xe36a4447ab365cf28538d2d02fc195d5b15a6a18fbf2dc0864f5a68986a53da0"}]},"version":"2.1.0","currentBlock":9942887,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":1253,"rpcTime":765,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","blockNumber":"0x97b3b1","from":"0xba411b9e641c51c8a7962d03cde51cf077dbf836","gas":"0x5208","gasPrice":"0x1a13b8600","hash":"0xae25a4b673bd87f40ea147a5506cb2ffb38e32ec1efc372c6730a5ba50668ae3","input":"0x","nonce":"0x0","to":"0x49ab060a6c8586fb9917d4197412048f1def3d66","transactionIndex":"0x91","value":"0x1410d379b1000","v":"0x25","r":"0xbc8ee342e9cf815964cdb327d82aab1c0b4b4b586f4eb33b2e49e9f89eb6f92c","s":"0x1baec64c5d3c93eec307e68a95f4b2c7e9840295c08f714a4e283fdb7b681e3a"},"in3":{"proof":{"type":"transactionProof","block":"0xf90205a0ed24fbc45d6a1ae29c998f98da6f13fad051076dc46d5807cd443fc95045ec6aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794da466bf1ce3c69dbef918817305cf989a6353423a09194d13d1c7209a62a5114e2510b0108d4f4e215440e994784da6282ad1dc779a004815dc9dbc57a7759c29afeb604e680f6b5816d833e097d0574eb521006cfd0a04a96f6456bb3ff96ed5c2dfcd72aa8bb514cf4b56cb64b3bf12395e9ade7f22eb9010080026c1b0451323c55082d49620618c28db80a82bc92c03c90014383382a1d218305111456053972a14115a782ca0580d20881a1c9e42405215c4112d02e812c043800e086aa4511cd84a5a89c91600c1480e920c2ae204783405b19aa4c659178af02400650101a4024463800680a012e2613a91e0c21687eaa2516b1209430096ca47b0004a504828503051205b419bc104d0d4182338260c6222600b400f4971e28206940a28a0b19059e422ad952519a01739cc45000873244a10800506722882c22647110f02890f0a00a53667e20004611d09a30010226005810086a208a106ca4a1105619c26540b0c432a24464a50503881200d1682e00010881a84a8707f6d7015511aa8397b3b18397c55383977658845ea43c488473656f31a0e5de79db17555a678536dc7ff0add74c0eb3259b591b2c5dc21431146f3fccd3884993ec801d63b2b6","merkleProof":["0xf90131a089c7a904e6b1f1064d6191df016832784a66bb774d02c8b467f44b69d68e1fffa0fc35d7da7fcfbf9a1a9226d08056497a46144284f1de05aa081681cb6a303c63a00acc07cc308f665363c2059fc33f2db97500b197dbcabea45ba132fa5eef09ada06bd360cae105fbddc419302ceaa353bc50cdf0f9b7fe868a20d09ab97a42ec79a0872c3ed4ebca04f21e9eadfd92b23e9e612c4c841bc0abb4f15e1695d42f2da8a0474d57941db534fa700ece15858d51c2198322fdf64142988347950be251bb54a022bf88edf2db7698c55bab2760cd3d95082a227b965a33618d4de810563bc467a0f616c4f8bbc59e3c523eacc93b350a674ee98792004ab3c4f234d40da95da66ca0c37da06c79bcb17616612890ccee8518679feb139ce33406a9f039151b0995098080808080808080","0xf851a0c0ab4bb48998e761227dd88c350a2c0c22d388c51f07c021cf7c625adac527afa04808b89509e350f36efc3c5a9d82f59d2fe0b9f3f1ae111ec68ee4ec7f59a412808080808080808080808080808080","0xf8518080808080808080a014f9a182ac5c9ff0d852c7e22577c8ea0355ca9edfa92393e591193d3dfef1a4a04773758b019f97afae878ae175afdc14a369811db93196c1a66d4f3dc53006a580808080808080","0xf851a06ee7795aa4754a2195e3fccb03512a6a5cf4814864abcb308098b52ebb25fe3ba0f3e8a16577842f474120e92880cec5630cef6bea5bfb8322ff37ccbbe9e767b6808080808080808080808080808080","0xf87020b86df86b808501a13b86008252089449ab060a6c8586fb9917d4197412048f1def3d668701410d379b10008025a0bc8ee342e9cf815964cdb327d82aab1c0b4b4b586f4eb33b2e49e9f89eb6f92ca01baec64c5d3c93eec307e68a95f4b2c7e9840295c08f714a4e283fdb7b681e3a"],"txIndex":145,"signatures":[{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","block":9941937,"r":"0x1688f0e25148779c61a94db81c1534e7abb2c78d57fb11e34f30ae9e34ec81c4","s":"0x0412f2cd9768f02a5df98ce2a58243fea2e53f8f225e613b4178c7676e6cf198","v":27,"msgHash":"0xe36a4447ab365cf28538d2d02fc195d5b15a6a18fbf2dc0864f5a68986a53da0"},{"blockHash":"0x2d5b4d02a4a756210a201cccf6eff7d97b9dd55d2b6bde78cabe082b1fe021e8","block":9941937,"r":"0x3334f002c6cd9153f830bbeb45d7010596dc4cd90b2ff206757593f33e05b19a","s":"0x577c4efb08bb047d7b8774c4cd0ecdfe8041aad0225d1bfb5e004891d1e9e90a","v":28,"msgHash":"0xe36a4447ab365cf28538d2d02fc195d5b15a6a18fbf2dc0864f5a68986a53da0"}]},"version":"2.1.0","currentBlock":9942889,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":508,"rpcTime":213,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","blockNumber":"0x2762db","chainId":"0x5","creates":null,"from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gas":"0x5208","gasPrice":"0x49504f80","hash":"0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd","input":"0x","nonce":"0x7","publicKey":"0x8c3801fd981bd86d46cb7e527fe79ec1ca5cfba19a6dea860f6f8f56927a7045fc9dc78956a2f1125e3c70932930a27ab4f54ee94e78d7609ef706da4b4977a8","r":"0x196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216daf","raw":"0xf867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3","s":"0x20ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3","standardV":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionIndex":"0x0","v":"0x2e","value":"0x5741bf83"},"id":1,"in3":{"proof":{"type":"transactionProof","block":"0xf9025ba003811fedae4ea5c2d69d010aee42f85fc52d1734a3403d68a82b63bd86baf5d7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07d5333691694496eaae51810c5e57a016c306f0f335f4b548ea8fcc45574a3f0a0bbb3ab701c45307f9e4556e7b6a0d3c174d842066d91e1c689737ae5242f7e11a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832762db837a1200825208845ea32673b86100000000000000000000000000000000000000000000000000000000000000008b2c88ca035a38a0753230ee0f1b28437f570b928351fbaba6bbd6d4a0735a7e34de2fa857e74afbcf472b54c3ead2801288741c88688b00d95642c41a9c3bab00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","merkleProof":["0xf86e822080b869f867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3"],"txIndex":0,"signatures":[{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x82457285707f9039b39e935d3b69a1b8efcc94d9a473e1383a41f65e5f92eba3","s":"0x047e4d4bd0fa3c96945bab372abf67001375d7dc9ce24519a2133d3afc8337ba","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"},{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x3f0c4166b5100c9cf84896a2da0e067e7a6a46ee66c88c60111eb8673046a2e5","s":"0x60cba2b7abd0c2bc5e32662b817a52c0a2c9663106f0c17bcebaa581292b227a","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"}]},"version":"2.1.0","currentBlock":2581874,"lastValidatorChange":0,"lastNodeList":2561645,"execTime":258,"rpcTime":254,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","blockNumber":"0x2762db","chainId":"0x5","creates":null,"from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gas":"0x5208","gasPrice":"0x49504f80","hash":"0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd","input":"0x","nonce":"0x7","publicKey":"0x8c3801fd981bd86d46cb7e527fe79ec1ca5cfba19a6dea860f6f8f56927a7045fc9dc78956a2f1125e3c70932930a27ab4f54ee94e78d7609ef706da4b4977a8","r":"0x196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216daf","raw":"0xf867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3","s":"0x20ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3","standardV":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionIndex":"0x0","v":"0x2e","value":"0x5741bf83"},"id":1,"in3":{"proof":{"type":"transactionProof","block":"0xf9025ba003811fedae4ea5c2d69d010aee42f85fc52d1734a3403d68a82b63bd86baf5d7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07d5333691694496eaae51810c5e57a016c306f0f335f4b548ea8fcc45574a3f0a0bbb3ab701c45307f9e4556e7b6a0d3c174d842066d91e1c689737ae5242f7e11a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832762db837a1200825208845ea32673b86100000000000000000000000000000000000000000000000000000000000000008b2c88ca035a38a0753230ee0f1b28437f570b928351fbaba6bbd6d4a0735a7e34de2fa857e74afbcf472b54c3ead2801288741c88688b00d95642c41a9c3bab00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","merkleProof":["0xf86e822080b869f867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3"],"txIndex":0,"signatures":[{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x82457285707f9039b39e935d3b69a1b8efcc94d9a473e1383a41f65e5f92eba3","s":"0x047e4d4bd0fa3c96945bab372abf67001375d7dc9ce24519a2133d3afc8337ba","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"},{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x3f0c4166b5100c9cf84896a2da0e067e7a6a46ee66c88c60111eb8673046a2e5","s":"0x60cba2b7abd0c2bc5e32662b817a52c0a2c9663106f0c17bcebaa581292b227a","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"}]},"version":"2.1.0","currentBlock":2581876,"lastValidatorChange":0,"lastNodeList":2561644,"execTime":110,"rpcTime":104,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","blockNumber":"0x114b55d","chainId":"0x2a","creates":null,"from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gas":"0x5208","gasPrice":"0x3b9aca00","hash":"0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4","input":"0x","nonce":"0x0","publicKey":"0x8c3801fd981bd86d46cb7e527fe79ec1ca5cfba19a6dea860f6f8f56927a7045fc9dc78956a2f1125e3c70932930a27ab4f54ee94e78d7609ef706da4b4977a8","r":"0x9749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809a","raw":"0xf86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d","s":"0x4106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d","standardV":"0x0","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionIndex":"0x0","v":"0x77","value":"0x5741bf83"},"id":1,"in3":{"proof":{"type":"transactionProof","block":"0xf90247a01ef625da39ab96124783516a110fc60f3760817acdd855a1605aa783c171f8bea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a4df255ecf08bbf2c28055c65225c9a9847abd94a0c1fbda7747cd2733e1344d765aa497cfb73a17b71f15de06ef5952530752ab37a01408010498362564b5c7cdea8ae1cb93be3bee5d9832447e16a11043ed88a289a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe840114b55d83989680825208845ea3379c9fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cde7b8416df595421b1d2c26cb476134b9c8e0feed3d5bde021e7f5aa43afe2d006f2ddc6d5c0b619bfcd0825dc45cd1768d9ba29783cdeee985fc25710c26cb4b6face300","merkleProof":["0xf86e822080b869f86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d"],"txIndex":0,"signatures":[{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0x7721c32e58634ef9ff58752acedb54269cb827c8909d024f5fa6c53bd94a42cd","s":"0x4785b591d5a592ae8c18c0c89700caa0193814589a167c0cd7206bcb700ff728","v":27,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"},{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0xbf4ac97d24925062f87074437dba9e7e7108731b0df65815150b9ab3a16e255e","s":"0x1e609d4e12d785e5b5ff4936460eab5eacc030e404163ebfde30df19c38ebfaf","v":28,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"}]},"version":"2.1.0","currentBlock":18135712,"lastValidatorChange":0,"lastNodeList":18098311,"execTime":142,"rpcTime":136,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","blockNumber":"0x114b55d","chainId":"0x2a","creates":null,"from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gas":"0x5208","gasPrice":"0x3b9aca00","hash":"0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4","input":"0x","nonce":"0x0","publicKey":"0x8c3801fd981bd86d46cb7e527fe79ec1ca5cfba19a6dea860f6f8f56927a7045fc9dc78956a2f1125e3c70932930a27ab4f54ee94e78d7609ef706da4b4977a8","r":"0x9749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809a","raw":"0xf86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d","s":"0x4106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d","standardV":"0x0","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionIndex":"0x0","v":"0x77","value":"0x5741bf83"},"id":1,"in3":{"proof":{"type":"transactionProof","block":"0xf90247a01ef625da39ab96124783516a110fc60f3760817acdd855a1605aa783c171f8bea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a4df255ecf08bbf2c28055c65225c9a9847abd94a0c1fbda7747cd2733e1344d765aa497cfb73a17b71f15de06ef5952530752ab37a01408010498362564b5c7cdea8ae1cb93be3bee5d9832447e16a11043ed88a289a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe840114b55d83989680825208845ea3379c9fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cde7b8416df595421b1d2c26cb476134b9c8e0feed3d5bde021e7f5aa43afe2d006f2ddc6d5c0b619bfcd0825dc45cd1768d9ba29783cdeee985fc25710c26cb4b6face300","merkleProof":["0xf86e822080b869f86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d"],"txIndex":0,"signatures":[{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0x7721c32e58634ef9ff58752acedb54269cb827c8909d024f5fa6c53bd94a42cd","s":"0x4785b591d5a592ae8c18c0c89700caa0193814589a167c0cd7206bcb700ff728","v":27,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"},{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0xbf4ac97d24925062f87074437dba9e7e7108731b0df65815150b9ab3a16e255e","s":"0x1e609d4e12d785e5b5ff4936460eab5eacc030e404163ebfde30df19c38ebfaf","v":28,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"}]},"version":"2.1.0","currentBlock":18135724,"lastValidatorChange":0,"lastNodeList":18060209,"execTime":123,"rpcTime":118,"rpcCount":2}}]',
+ },
+ "eth_getBalance": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x1a6ced2b2f49e7d","in3":{"proof":{"type":"accountProof","block":"0xf90212a0e2443f35ce0a0c3d5033335bace8d604c4d08922bfdfbcf3999153a39702edd2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a09886aa2dca10de06cae31965a715e6852b3ae60cca7451ca9dfd62c4caff55fea006870c2b4334ab209c0702cd131787c41d4fc81cf00d79baa9f4ae3bfacd2a10a00f5c78e4538c114053c6dd376ae9c2d10a259810fd6652f749bb6931fe922e47b901000444008004804008000822004800300000408020000001080000011002000000000000300000000040049000001001801000040840020401000000000010101000008000000800094109000800000000000000c2032080408000400000000020000100001200000002044000010008001102100028000000100000100000200160288002000002800080000980000000800100000003002009c1060000b02080000400400002004002800080108090000000000080000008404000101800024000000002048000100410000004801004000040000414000000000000100020002400840100080408882000404000a900040100000000008000001000100010008708024da0a48fbd8397a0bb839755e483200dcf845ea33bc29150505945206e616e6f706f6f6c2e6f7267a0026165cf58667f5e38cf0b392f0c6c62fe6086c4db779811ae11ee8bde84ce43882207d7197d804cce","signatures":[{"blockHash":"0x367682c88150fc95e1ce2219ef352df5d01fe9363fc51df9dda00ccaf8722c31","block":9937083,"r":"0x5788f12cbb5495cc08c82a9921bc95474a59cdc62f05de4aa10b26758073d6b9","s":"0x198be1fbe59874c8cd84fe41d4734c56800fa3eab8edad87da67a879fdca57e3","v":27,"msgHash":"0xbe085a17867f4cce74b2916e97761998dff46f5f8f6851942bff363c75beb79d"},{"blockHash":"0x367682c88150fc95e1ce2219ef352df5d01fe9363fc51df9dda00ccaf8722c31","block":9937083,"r":"0x2b612f299a14801b4e7dfa0df383bea5c8843dd2c55dc080b5884000f5dc9074","s":"0x17ab417aa1b7042ec952ad867ecfc2d3f46b2bbb06c89af6b2788698d59aada7","v":28,"msgHash":"0xbe085a17867f4cce74b2916e97761998dff46f5f8f6851942bff363c75beb79d"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","accountProof":["0xf90211a0e687dae51c96927cb5aee59556ea23803054bf78e5b6e48959ac935aef193bbba0939e1b39f52a15270e93ff82fd2e311959592e0f383208715f1e935682b135cda05cad29604abfbee863a3beaff20242b36faf67a4969190d34008e707fa37e6a5a04b2b2158489117a85e8359f62f7e792d68896ad39dd4890d901d5b0ae5809b63a0d12f4ee8734a720db427fca5861ae6914dbc945e592c1156d9fe748792fb86a7a097f7583d1936ea3a68dedb12955f1984d4b7c8caa2ddb7c5e32016fabbba63d4a077d9e93be19f6d280139a336d0a57d3d62d8ca9a2fa431c7425dfe118a5c804da0c12360dc07a45b8b83d5afce55855fd204b48b4f8a7450e55bfc7952fe8fe831a0af12264bcbd6c4fb626afc283e60643ac0f41f79a9b0ec85181f41ebcf7a998ca09821a81f52c717111a02c4f770df052873e1c2b7541b02a784eb56e71a74ed7da0bf16f1218b8837b7315c21c7cbd6c94f8f8583928cef138e5fbf0959de3559f9a09dc107205fea88262f40442e2c647ce9a57f2abaf7ca3d31791d773841ff716da06e7ae9fc765e6c16e27a8aafc7cc7f573132dba78ee889a3ff5e78cac0e9e60da0c167e1bb9312d026ccc6a42eb321c5cbf19aa0f294652c358afbe3b1b2ce677ca06d64c07bca8a2c97307cb33ac35d7f122a3160ad61eb9559f2466eee195a704ea084450d8096898cb3f85d3ccbc5c9c2002c94f040c3fa4d4f1670a0b0b7d54dea80","0xf90211a0bfba062d824cde18abb57bddef5e28cfe82c2a02d6f3b547562ef7415ea45036a0fdf14af8ac7d075ee35423b78efabec6efff09391ca9d3d4b25cd257c3b0d4e6a086a15d6a2f5f67267306d87dca4c839fe572fdde069a3bae610226e5c69c1dd3a05f3e12e8970d336a1d25f1857c3379b6a8cba26e465593cad38c3fadae7c6829a040a911911944c9723e30d05356d42a4d42eeaae43f25b28c7b197b51bdb2dad8a0c06b29591de01aa92af26a35be052b62b47fe4293279b0740b1b1544c84602d8a0e38f86ee589e35375951460289b87f8aa9419869173aee496e706f82f7cb3363a05244041e5c2c34c75372dd28b3705441dc1d0155b0c031c94df15477771c46fea003a5ea625b47f06fa00c7d66b2e093c2b983649216810f5857836e4f1f1ffba1a0aa3e42a9895548ade09e7fe258654225840896a31d986d343214c7e63b63d308a0d30bbe9dc9edf04028c27115473a65f84510f0af88287f29c32d2d6d32a436b4a028f93a02cf197d8c813f94bf690011089a46b109de598b8627ed7c28233ca495a04688ab01b721db9b779c7caedb8848bcb499f1b4c1f1dc3d95db9e538002a82ea041bca5fca31d682338c5fca30bf2483e068d3423a47d98cf6efb4c4dc08ba623a0a4680254d75cdea92f8f29772a7a1088ac07bdc5602c385d6c7b8b51bc29a54ba0a61a891f3424d854abf800915f117980a6a760d898509a3682c4f646d9aebf8580","0xf90211a082812670728fd4fa90d6e04bafd796cce497078c9c4d812260cef40979ae51a3a0590fd629dca51e60c60175d4d91e14c966f116b1f0d0dbfe404e254d890fa978a0c09cf42d6779bff689206971d8d214ade88f01a1455b4d767cff3450b5c05effa06d3ba07c439e24962968384fd58da747d8cd87a3a31bb3d73b692e0e5e3dc8dea00893f1d54f6616520186b0836f48b4566cc75ab67241fb48cdd8200de9d84e44a04efcfc12372187de9cac26c21d37d13ad02b6999ecb2308ba416be917b87dc33a006d8f6bde492410f9ac4228baf82139190c2ff7c034bacf84e0b13f475a5a28fa0abd4af9398e52af87e5a29b7acfa527fd21ad8422d16f28a1a78e5593cf9b28fa0c933cda2923d2a699fa93f5a04917836c309b5c6a70fdcf2bd27c1a54ab319f5a02a17d17f178e0a498945c9d2b04a8da783fc2996b80ba8b1d47e5101ff17240ba0acd22acab5857aeb262f4080f173c73a006eaf15bdaf605e9b1552915effb6cea078d181bdaddee38ac87202d1850dce602cd725e781ead91313427cacb2353dcda02ef63d3f0582429bf39ee1ad098a05c5126c0ce85d1e715bc9f64913b7066a7ba0f9ae6b91926f9254203c57ec7a084cff759d57f57f87ab1bc40d76be8d8c325da0c0a4a33b56c004141f2f387d542392430669e465a0335d528bc1a3e146df01fda01b6141aec009d4c324a1dbb1fab6803ef31f4bdc4e6488dd6f9e520f92efcc9f80","0xf90211a067bfb6b26daf72b32dfe485c6d57d29ec8ba554fed256f3d0077cc4b943d2bd8a0a682cd5f9a1173b8e99e19c9a7cbe1f33c989e39ecf29a4e99128c5e661ea597a026c3a89ab3531570fc6fb2d439fc24e7aef7edceabc960d7159cadbd9d4219d3a073f7793df99129b00750bdf095b0d1dc33e005bc6a069e639ba2e6cf90d3bec8a01eaa2aff03af6cc4824649800961be5908fb241874321a60c20c8084f2b46b88a016f217d567c29b2ffb7e95f8a519007437bef0772ec38cd54f2f1de69574913ca01a46b5f0ea81897d77b311793dd1a5adde52a2d35f04dd5cbce085f51b833c53a0296ce9dec7156874966dc12ee28e84bec8ffff99830c099455b7920b427152d6a0c9f19a01a93667307166dc6ee7bf4c5bc4e93c0a06919f5f7b165b2688e6958ca0fd283f43e391df4041a92ba13c7be83db7da9dafe7aad81b86398438e67ce03fa02c07aa3eb2e24702cf7b9e2072d0065eb8f9efbbad21c11f1eaa5b0bc4783219a0a733c927d0fd38d0e043f82122b2fed87d102a9f6600926668615905093f68d8a0e491aa7b042e2ba678a0f469ca3fe9422cacf7c86eb1293abc971db7e489e80ba02e5345963b1bc31386947eceef896cc3dd0c9c5033a8e39d93dec0b860d81631a0a1fbb320dcb6f1525e29bccff1b35e053da946e4a0de53eb98f1fdc2f99e9b90a033567ca2cef1244a5650ff7a06431d20801cb4214e88400312895777685ecda880","0xf90211a0261b5967931f883ad8f9bb1f3f0c6b23a2458aa2306f79d811be527adc4dce81a0d70b6811a39084c31a0844d992fd1d1333ae871dadf570b115804e2e44f8fc80a08776484be1c12cf5369099e303761867b5dbeba8fd3d181f0f2e8f0005fa0b80a08c11c55944ee7cf9588f541615eab7de3b980b888aab1328317fd0ce619bdc00a072403f7b5d300db1ff2fb2921da0abf78673d1ad998d3632d4f235a5b5ec1b3ea0655bf907f8fd977e5f201586831caf0cb60619bce9a7d95ee560e07b63b8d4d6a02ed85b49cac72581fefa75f224b954f638fd3c9fe5de10b2ebaab520276fdbb1a056d21124e2892a9ebbf0c3268960c618884704c774ee721ac339c5c9c0ce19f9a064ff7aa541719eec43608cb72aee413850ab4031c2e1f2e18138013f0dcc292ea0a2b7a273c61b63d1e832f505c26cdecbb87d14c061a2856fb0191bdf98d6888fa037df45442419a2c54e69e2b4e69360720823a8151bd8be982a2cd355790235daa0de135dd855f549fb56c0a1a1859e2d2fbfdb9bab664d407fb16d54a282fc28e4a0ce4600309c4ea2837c39cead22af139d031c0636bccc8857289d6ab8658df475a0a08808a7dca9d11678a645af7645deec46568bac26276ede4e03fbe237b1dcbba02684be44f2cb6297191d5a558e68e8a6a7dd33322d16f581a8e4f5879336dfc7a056ecc5fa38d5634824726837b6f88dc88b48274ef035153ab73e18aa10b0272580","0xf90211a0222bd237a2d10e712e2c86d9dac5c8a7c5985c5da958d1fd6142b37ea18ec707a01095094b5e902b686060bc62e4c9d7103d31b7dd4cf879fdf6cb036bd83add67a0d0bf92f6895986dcd82fb0563e9d9c5d14f37e05ce053ddde9c7e9c7fc30c2c6a0f37181ff7a96c723ba931bbfb0db1d37d3752ad7bcb792a2f3c9d691ba475d99a06278e87f0456db8f07030794cd555fc0f47cf333a8a7a2cd47380963f28ab4b1a009e805e5034c070465498496ccd8c9926e134896cbbe6142ec3acea3052ea373a0d1d843eaaaaeef9cb88e9f1bf8ef9e29e14273ea86fa4c5274a686e322ba7f91a0acd7a6879246a65755db29b5fa1406990f401e31ccc0363a80c44637a567deffa039f9645da32ab327f07a72721794a2f141fb1723f3f6027ec84e38a15a539fbea08571667ccbbb5cfc39019c8a7990beab1ed3a62074cfb6030e434f1a27d17adea07eac5c62ec4eeea7f44af4d0dbe790cf1c17536aa3ae11bcc97980f1f3b41cfaa0858002a1e730f328f3f02b99871f6c469515068b601b47dc15cbe0d9b1d5fdcfa0baa3fa271fc8c381bffe19e0b81401df254d6f305f3ed243d96deb3cdcc170c0a01804356e51098c03da7dbfaab03b899918de0cc79a30350a560380e1d5cc153ca0ff682943d177c894e7d079529bcd4053b20fe9c3f4a20afe87694b1d820a7a6fa05a64d0fa6afd9fe7705a93e9a6642287e87e699907b359d9c60de6630e9a5ca880","0xf8b18080808080a03f706b8ca48526bbc6a05644d03576a21119a7e2a7efbabcf0216f9aba999af2a0a6a3119e34b9242fb240c2a5c4fadf556f9bf8908bb4b411e63f52b8030d62fd8080808080a068ca5cdfb862ff949e832afd5f5031674bf756c03e6eb33485b3c0814b08b2b2a07fa66234a8621a311dcea5dd718fb7b35c90df669bbae61d2f8c5c1f8e439150a00c7b0ee28b5dce8efac5964ece41b3aec29ee10d5243085e3448301ae111d98b8080","0xf86e9d32bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c088801a6ced2b2f49e7da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"balance":"0x1a6ced2b2f49e7d","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x8","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":9937089,"lastValidatorChange":0,"lastNodeList":9936896,"execTime":281,"rpcTime":172,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x1a6ced2b2f49e7d","in3":{"proof":{"type":"accountProof","block":"0xf9020ea0d1ad819c02a17d8470eb8505a71e3b271518d544da37f17c183a41b18ae6193da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479499c85bb64564d9ef9a99621301f22c9993cb89e3a0a820c780d48992c9f2e51ac551c41231671d711f673a131ed3f29fa296925786a0cfc29991d015af66ac367f927b9e8fa89bd0651d905fad65b080ed34a2822e9ba09dde1635a38de16a625b621fe4742c12738376128cfa8c0b1e2c81053a5e7046b9010086001a32001a500580049800543380102008320494289540c0e31100000ab610c28a409228231010c09486000808210696086b006200241094108144343880984108015006006481e82003089180780e6202b04e40602049c2040830081d627010260820022584100907401000f9080030a642605ca41518383920565192728101228c4442200520044226203004550b82414348190392030154101f181820a12654046061083443760e61c010558e5a10a8418494820894003f30644004405aa218510a6d0a820328306010009aa7c100847205080c044288b9a8d4100631c12810c5015012110980aaa8804201aa04620440a044805884802040304810aa488707fe4b99ebe93f8397a0c38397688983961093845ea33c578d626565706f6f6c2e6f72675f36a0773246f9db0a34f5e4c7f3233b812e4fcac793727cf023d8faffdfac6911521e88ecf168c80f0ff3d2","signatures":[{"blockHash":"0xc006d0070404916f462f525147cc67286b27fb60acc353c2f953d5300971e699","block":9937091,"r":"0x1220c04740545239fd800f7b4ab9d06b3a4c8f69ebbda96f88fb234a81b459c1","s":"0x0dec6ea040e7461e8b72a59b7c51bf5437de9411e13957eb40259d4554d51877","v":28,"msgHash":"0x7c59a5d8a604b76e05fe5652f3360f5fcdf342a140063398d6383e7f6c535142"},{"blockHash":"0xc006d0070404916f462f525147cc67286b27fb60acc353c2f953d5300971e699","block":9937091,"r":"0x4eea0c2edeee23d8b813cac2ded4b7b0db7c660c7904e00421055f3c4451bc30","s":"0x46e85da8adf350e17db9a621eb15d255c3d463ceaf0e7a75140c96b23e52cd2e","v":28,"msgHash":"0x7c59a5d8a604b76e05fe5652f3360f5fcdf342a140063398d6383e7f6c535142"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","accountProof":["0xf90211a016f39956babfdcde3c44c2ddcc169bad95deae747e2c0604405b3d9e631d99e4a063793186179fa578b0e973563d8e5917c44f60024646f3adfcb92c19cfce7867a0b8a5029f251d02f495e0f47cee123998d4776e696bfb8a7387279475b5ea9659a05c73c1531f2b4b347c582464a721069b52d33e8ce3374fb2a2e6669ab83e2071a029c1521e1cae6945e94c29ab0d0e08eb04c8af3939192bba6c5d3d8deab62d7aa06582652d754866c7e0b0e7f790a555174dd5705308d22e60f1f6e6036a8ea75ca0e80f2ad43bb99fa5c9e3f3cbfaa40a57c874090ad43575a2409adde9076d05f5a00fd7ce3ce2cd02637aa723c75d284c356bbd7ad1d45a5538e0998000093d5db5a0ac74e9ff347e4128faac99506d50afe22c502c11785a315be8e930c3c2146f65a02ac69e6aafe392f514a89ab81362948436f34a993623a48c887086f63796f44ca07f091aaac6e9f37c841e39bfab7801a19aac3b0d92ca1b9fae6fe9f37ec3138ea0b9bbaeba1d12a106f1c919c9c55867f68ec7d59d267bcd3c28e9389cd208b9b2a0b39d23e1cb799c58cade21272e9b5335e6617fae660a229a8f2076c4dc791984a00d866200d7c60cddd9bc9c541a23694d2409962480ca6adc8a5c7f6f8fafed67a08bfc50df1e47c2ee65b5e374ad95b2044cd95ca6b82965491a9172bc45c85869a0cad03a80c236a0451ec39641aef2abafd6bd264861ae40336f10322bae492ad580","0xf90211a0ae03fcd510290f50a05021b34a218044a2176f72ad0f7a31a5b847d2267f80f2a0914603045ed0f8f0a28c6a2e07af9c1928a0ffa9dd5df6bc40d5f33455ef201ca07118180f199562a68fea57e3c6aa3a6ca365d1eded70ceac37541f50baa1bbc1a0193d410de70ba0b3793e96800610f1a4a3ae205d1389c1fa5c57c2cb53532fb7a0eb42a3f8a9701b77192657abd46bd3bb279e2bfb50f487eb44ca2a9060c57b09a05da9e1c2b9c0cf96e899e7741efbf882261978df702cd2be747c31a8737c03b0a04205c2459bdedaf61e21f34fc89dc403bf38af9c6012aeba393527095681f995a0db5c14a4aeacfaf88e8cc56467b5d23bcb2b479fb726f9525a4cfa6a666ee58ea0bfb56e644a7fe9e3a32b9d93de59cd9ae8307cd9e9399159cacc1a34c8f4c75ea035fbd6537b9fdad34109f8ade72f710cb49fe4c6c6782fad66b447149a36d9d9a0d90b9f90083e1ee14667289273d5c0d937436ad2aba4851e49d8efbef72626dfa0772b9e0f3adc27ccf5a47234e5be906f7716f2805240738dbdf286aca67b676ca07c51823c3490ec513ac54ee9998fcd6bf32c348e8c463ea9727767490c65be5aa0b0cb8d6e7242e2cec342b621d0ef5cecaef5f3524e644d30b582bc964ffb69f6a06afd8b017a2cf0e21200fbe08fc4c9a943b6d27dfa3a60c9799811d05802dadca04669c7e4ee68d84bfc4c6fd5960ea5b052e16fef2ac725c1e33863e746c639f380","0xf90211a082812670728fd4fa90d6e04bafd796cce497078c9c4d812260cef40979ae51a3a08847eaef844dad32e700be786cdf8db94ff5ec5d1cbbb3b422f6269ed772ec46a0c13084815f1d5326f50698d226bb417c1ff34f810e313f28991db59d51577bd1a06d3ba07c439e24962968384fd58da747d8cd87a3a31bb3d73b692e0e5e3dc8dea00893f1d54f6616520186b0836f48b4566cc75ab67241fb48cdd8200de9d84e44a00e04ffa8bf1982eb0c7032df3583db1c24312c14556b690b7a96af6f9f560510a0045e87d7034c9eb535a0aa38b93a9d8af39eb58ced56171521d2a95f0313d4d9a0442d1412ebb00c44a4b90595342de44554f01ce08540a07ba7b3451832e00443a007f9b9e585d966c7a574ca3dac306e6789eccc38e15ea3a5ac909d0890d28e9ca0f72a52397c06d1fbd44310e8d3ba375bbc2bd2d785c70a3fefbd30b9465db958a0acd22acab5857aeb262f4080f173c73a006eaf15bdaf605e9b1552915effb6cea075a3d8eb3d096fff67facf64f91b1e3857ac24ef4acf0c3e013ff89b6582e375a02ef63d3f0582429bf39ee1ad098a05c5126c0ce85d1e715bc9f64913b7066a7ba0f9ae6b91926f9254203c57ec7a084cff759d57f57f87ab1bc40d76be8d8c325da0c0a4a33b56c004141f2f387d542392430669e465a0335d528bc1a3e146df01fda01b6141aec009d4c324a1dbb1fab6803ef31f4bdc4e6488dd6f9e520f92efcc9f80","0xf90211a067bfb6b26daf72b32dfe485c6d57d29ec8ba554fed256f3d0077cc4b943d2bd8a0a682cd5f9a1173b8e99e19c9a7cbe1f33c989e39ecf29a4e99128c5e661ea597a026c3a89ab3531570fc6fb2d439fc24e7aef7edceabc960d7159cadbd9d4219d3a073f7793df99129b00750bdf095b0d1dc33e005bc6a069e639ba2e6cf90d3bec8a01eaa2aff03af6cc4824649800961be5908fb241874321a60c20c8084f2b46b88a00f469dc993b8b4c3bf40545b3362dd65521b895b509eb9ecad7ff38b125f7a19a01a46b5f0ea81897d77b311793dd1a5adde52a2d35f04dd5cbce085f51b833c53a0296ce9dec7156874966dc12ee28e84bec8ffff99830c099455b7920b427152d6a0c9f19a01a93667307166dc6ee7bf4c5bc4e93c0a06919f5f7b165b2688e6958ca0fd283f43e391df4041a92ba13c7be83db7da9dafe7aad81b86398438e67ce03fa02c07aa3eb2e24702cf7b9e2072d0065eb8f9efbbad21c11f1eaa5b0bc4783219a0a733c927d0fd38d0e043f82122b2fed87d102a9f6600926668615905093f68d8a0e491aa7b042e2ba678a0f469ca3fe9422cacf7c86eb1293abc971db7e489e80ba02e5345963b1bc31386947eceef896cc3dd0c9c5033a8e39d93dec0b860d81631a0a1fbb320dcb6f1525e29bccff1b35e053da946e4a0de53eb98f1fdc2f99e9b90a033567ca2cef1244a5650ff7a06431d20801cb4214e88400312895777685ecda880","0xf90211a0261b5967931f883ad8f9bb1f3f0c6b23a2458aa2306f79d811be527adc4dce81a0d70b6811a39084c31a0844d992fd1d1333ae871dadf570b115804e2e44f8fc80a08776484be1c12cf5369099e303761867b5dbeba8fd3d181f0f2e8f0005fa0b80a08c11c55944ee7cf9588f541615eab7de3b980b888aab1328317fd0ce619bdc00a072403f7b5d300db1ff2fb2921da0abf78673d1ad998d3632d4f235a5b5ec1b3ea0655bf907f8fd977e5f201586831caf0cb60619bce9a7d95ee560e07b63b8d4d6a02ed85b49cac72581fefa75f224b954f638fd3c9fe5de10b2ebaab520276fdbb1a056d21124e2892a9ebbf0c3268960c618884704c774ee721ac339c5c9c0ce19f9a064ff7aa541719eec43608cb72aee413850ab4031c2e1f2e18138013f0dcc292ea0a2b7a273c61b63d1e832f505c26cdecbb87d14c061a2856fb0191bdf98d6888fa037df45442419a2c54e69e2b4e69360720823a8151bd8be982a2cd355790235daa0de135dd855f549fb56c0a1a1859e2d2fbfdb9bab664d407fb16d54a282fc28e4a0ce4600309c4ea2837c39cead22af139d031c0636bccc8857289d6ab8658df475a0a08808a7dca9d11678a645af7645deec46568bac26276ede4e03fbe237b1dcbba02684be44f2cb6297191d5a558e68e8a6a7dd33322d16f581a8e4f5879336dfc7a056ecc5fa38d5634824726837b6f88dc88b48274ef035153ab73e18aa10b0272580","0xf90211a0222bd237a2d10e712e2c86d9dac5c8a7c5985c5da958d1fd6142b37ea18ec707a01095094b5e902b686060bc62e4c9d7103d31b7dd4cf879fdf6cb036bd83add67a0d0bf92f6895986dcd82fb0563e9d9c5d14f37e05ce053ddde9c7e9c7fc30c2c6a0f37181ff7a96c723ba931bbfb0db1d37d3752ad7bcb792a2f3c9d691ba475d99a06278e87f0456db8f07030794cd555fc0f47cf333a8a7a2cd47380963f28ab4b1a009e805e5034c070465498496ccd8c9926e134896cbbe6142ec3acea3052ea373a0d1d843eaaaaeef9cb88e9f1bf8ef9e29e14273ea86fa4c5274a686e322ba7f91a0acd7a6879246a65755db29b5fa1406990f401e31ccc0363a80c44637a567deffa039f9645da32ab327f07a72721794a2f141fb1723f3f6027ec84e38a15a539fbea08571667ccbbb5cfc39019c8a7990beab1ed3a62074cfb6030e434f1a27d17adea07eac5c62ec4eeea7f44af4d0dbe790cf1c17536aa3ae11bcc97980f1f3b41cfaa0858002a1e730f328f3f02b99871f6c469515068b601b47dc15cbe0d9b1d5fdcfa0baa3fa271fc8c381bffe19e0b81401df254d6f305f3ed243d96deb3cdcc170c0a01804356e51098c03da7dbfaab03b899918de0cc79a30350a560380e1d5cc153ca0ff682943d177c894e7d079529bcd4053b20fe9c3f4a20afe87694b1d820a7a6fa05a64d0fa6afd9fe7705a93e9a6642287e87e699907b359d9c60de6630e9a5ca880","0xf8b18080808080a03f706b8ca48526bbc6a05644d03576a21119a7e2a7efbabcf0216f9aba999af2a0a6a3119e34b9242fb240c2a5c4fadf556f9bf8908bb4b411e63f52b8030d62fd8080808080a068ca5cdfb862ff949e832afd5f5031674bf756c03e6eb33485b3c0814b08b2b2a07fa66234a8621a311dcea5dd718fb7b35c90df669bbae61d2f8c5c1f8e439150a00c7b0ee28b5dce8efac5964ece41b3aec29ee10d5243085e3448301ae111d98b8080","0xf86e9d32bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c088801a6ced2b2f49e7da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"balance":"0x1a6ced2b2f49e7d","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x8","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":9937097,"lastValidatorChange":0,"lastNodeList":9936729,"execTime":1073,"rpcTime":968,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x5673694a100e8c98","in3":{"proof":{"type":"accountProof","block":"0xf9025ba0ab37996eea782dd49b61be8194fd7cfa0a1621adb4b16ebbd6f8bf85eea3d78ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00ac20650f7bf675110185eb5605b95322703d694439023bba3d3168e169271dda05bd6dfec98cfe47b4b1e5d09da6835484216d393f837ce1196b893c934fc4b1da0d95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028327650c837a120082a410845ea34754b8614e65746865726d696e6420312e382e31312d342d3035356234313536362d3230ef088db330b299838bdd018f57b0ed9daf0e69dbdd8cfd8242e0a4c9e88efe1949697c2c9732dfa2f8787a88f478a7c080515a18925945ce06481381a0f3c8c600a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x0108673cfd281ca59ffa0482339c02fa0a5690906f0cbc12cd7f463dc9f82513","block":2581772,"r":"0x909f4f4be27489552d187930b58760c2752a4579ad8be6a5113c8a2821049d05","s":"0x7e34b1cf114f8490569f1e7f13d5f59bc30449a14d8391f61419bcdcec7881e9","v":28,"msgHash":"0x64b1b92683d6eff9b3513775a9d7c15f7ccb5a101b266f23c104c967c964169c"},{"blockHash":"0x0108673cfd281ca59ffa0482339c02fa0a5690906f0cbc12cd7f463dc9f82513","block":2581772,"r":"0xf8617359fe5ee1a2ad8d2c4ab7b2098e8c708d104e7ea836c91217b6cc387624","s":"0x6e15587baee852c41016cb133317c897be39fb75bd710b58d9ac18ed1c8bc466","v":27,"msgHash":"0x64b1b92683d6eff9b3513775a9d7c15f7ccb5a101b266f23c104c967c964169c"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a031f7a490152d9198ac6daffc53a53f95cbe0bd2baacbfeb05729410c95c53dd2a0c4d9672b4fcd3ff260c64d5766e68570c5a0396b2dc1d1a13e1545d8deffca2ca0265a0d2f22820756c40f40bcaa9303e363698cb38fa9c0f77d5ff1191a57fe5da089550a001535f132b0db17cce0aaa0421825964a8b3c25ebb555286edbd4a6eba03de3f03a4f4367cd5300c3534af6020347c696da0c174df3603097ffa73e01f4a0f416297e9d914d7a7c4ac344a10ffdf9436ac81344b927c98466e1d5d1eedabda04465cd0dce8305322e08cc68ed634a35ec33122eeda78fab3993263d71d60c9aa04a9aa32e5cea9a94e01f218e5e35be71970f700beacbcc0b68aca671939df763a01feebd59aea3772a3f794afbb74e09435deb7f05f48a9ad67b0850de27c2da64a07f783ba293711c32da56c66a91832cca47a942f59247b1c57ff576a906ac1db2a0aedcc7727ad9f5d4f8532daab2f220c1ed62907a2f10b98761d4eae22ebab0b4a0d7b0930016dcb8499069ed9c90e9a000f4fc130577e79062767526a262f382f5a0e40c8e5fbf4be625f4b53d7aea8b1b7b594dc5ba7a3944784dcd655b6b67c43ba068bd9e6411fe1e7cf943d5ec3bd4a2d140d056ea48a7f203318a84a490c3e080a08070b7b76ecdf51c42292f292ccbe2cdfbb8348863a97459a2002ad8d758a601a0036a6ab414986337c97ff613b85786943d4864316a5ae5f855866433a9452bee80","0xf90211a041103aaa4ca5ebb29cf3287410de9367720dade6381358f5605fe6201c1a5699a072a2bbfe83f4756cfc96f1f2d43aee5cbc457fa2be81a5dd7cb27bd434afd853a045f7df1d084faf674022712bdfa093d00eaf5a0cde0df976ea1b91ea9e4b53c1a0aafa71caf1579972c1ec1e3b3459f2e8337feede173ea8c056b5aa19a2df693ca066b43fcb732a6caee76a79939e5c1f2fa7983eff26bda2d087caf01594572d4ea0fb9af08296918cea43160b23ee460c8b13b910fef834d3761a1e9ab7dfcd87d8a0ea5a616a1a3c8668b1a0620ec135f0614b23b0e9191a19ae1eaeb56c645fa5d0a0b6baecbac90e0fcc76a405b35f0a4762fe45de34177fd67dd7f769e8907b69a3a01f98f4433aa0ddefa8e8ee2a73e3d3912f8b2182db688e25c25887bf8b546f6ea0be03f9b329d28342d585d4bc3edce4318dcb7f3aa55d08edce31e6f514ab5b91a078556c735c76898f5cf1e27a6108837d1b2c8d6e92bcb977834a48c9277920c7a019d353880a2933b428fdcf3eb5f8f519b3347b7bfc17086b099976d210a92562a0a8bd7540aee53c82449c785e882bc5f1938e14673ab504373c970493f6168115a03ef89f0baa5214e6e3df2a979ce316323756368decc9e8957b585e2103b2512ca083866d677646f27db8ba320e5e5a125f797c8421668c67c33e1cbc49f57663a8a038e0165ce0896e6b1e0b5d36d39f54c805a4a24fea87c7b233d385f6333c448780","0xf90211a0ddede8812030ee393d328cf0c91c82816c9f96bc0a66c1af65cb5f79b1637a25a0da3c2a7184e0f9aaddb6cc5a7a20d4413f5ec563e9f1761afea77e99dde4bbada084a53c667d75e65aa63d8cb04be9355b3b82ff081f715b6bc525435d3ce8f6c4a0840e71f98dfd18f63e241499c0eda112c083d493a75e5b357a328df4686be427a086903192ecd5128ec2283da7037ece448b7eef2ea0ecca0e4a2fdd3c14a1ed07a0a32ff45265b0c08eeaf2b2ba83cd4990f44c0e01eb99c7f86f3ea350b09fa385a06da4892c9eccd43a735e10974868099e36a51f728e9125bd7e1d33a9a9cfea8da043ed6ee56c0f506fb5dbe8be30a0bb4e0e1ffb6d2d5ac789f6dd798613cca8b2a0bd5569a2c29e66062ec91ba094caf99b5553053e81e6e2d3652e912cfba043eaa03a11de148e3a3e80be5112af4f6151918b7070230aedf3706cd9aa80cc258176a0f146ca9568124965eb8eea419288d2669eb061d3e4c35110bc8d0bc4e7fa4221a04067851f46b1aee36e281c8bb6cf4db12f28528a50f83fcd04c95c481b2b5993a07299cc91f3a668d8730a4af5b821e3082a4207e3cb880a296970fd5e3342d8fba0e0b46d93dcc1fda8b95f4161f384136d6d4913b3245fb227f58ab2411d97b6bea07286a0ad8952431a2d8f0e2b0a96938eeb9e498b6c588a8b03e70cacbe8fccf4a045be1f06062e86d7085b962d85ef562a8b22eb0e11457f0bdc29f8ad4209036e80","0xf901d1a02bbb5dda7a9bc9df45a8ac1bbd5bd0850902d193b56332a8c55150b214c8d987a071429682be3581068a0273a720de04ddeda04080fed8247881c526f68cc050e8a0bccaecb6bbb5eb8abbe6f835696e25ea86c8492943f0b754f6913baeedc1a9caa0a8677936e6b7f8e0c7abe8e569b3c9f739ac44e11e03cd3f37c0cf562cd98ad180a0b630e0ac24ec2b43a36c0c9caa61a4b5fa6ebb83294220fba97d415e8e770625a00cddc5c07dc61fcdd9ca75b7bdbed677ffdb077622f9142b71ba3f3ddb7fa9e5a0b6f6e28e039468dcfb64617d969bbe39047326276919ac13c4f4641f0ad475a8a03f74118689a48bc9f9682bd02abc86087f9966561b1aab25a898c6d04535c5d0a073163ac85225f8ba7a9a5dc6a42b062b85b8a5e5a5e38977c1f9890a5e6581c5a034d30b0b58bda0f4b5f3059e1132807678b0e7d0e6d303a31f24bc64dfea8dc180a0ac9e65b51107095a25be9c078ba1a134d7b185d8100e3f39016291328e434905a095c6fbddff1af3ee610bbc83fd48bc3eea0b725054aa1c4b616f08b238783ac5a021eaa5f9d89b8ad76a4898b1f8c58763a323bff30cbff1de36f3c7a288712cfea0e0b0e6bfa2a0b87c53eb9f6ca07afdb085a556bf78e047d98b32dbc287d6b13c80","0xf871808080a04666e3a5987e0a9cbdf1a330d25c6d3126319bca62404350775a62987abcca1ea0fc889a49c4876806dd6bf3dd10eaf1b835b5a51fb12565687461db7f5d2279dd80808080808080808080a0ebbab5b534b8863f30247c30489edf3a8bf157496db64869a46a3a55d3289fb380","0xf86f9e3a52bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c18885673694a100e8c98a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x5673694a100e8c98","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x18","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":2581778,"lastValidatorChange":0,"lastNodeList":2561645,"execTime":193,"rpcTime":97,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x5673694a100e8c98","in3":{"proof":{"type":"accountProof","block":"0xf9025ca0a56e21b92f8546a5e8e2c257ff4b870381c9571c973e03d6f3a7a0103086a03da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a06194df8b88962ed834af90c742af4cb3a37d56fbe5fd88880a294673e51fcfeda0b7841153ffaafd26e7a253385e476d65f9ba48421289eb260c9f4702bf171a85a0b5fe7a8686f50e4ecadf6aee4ea6a8b48ce1bd8983452906c70ec5bf89e1a929b9010000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000040000008000000200010100000000110000000000000000000000000000000000000000000000000000000000200000000000010000000040000000000000000000002000000000000000000000000000000000000400000020000000000000000020000000000000000000000000000000000000000000000080002000000000000000000000000000010000000000000000000000000000010000000000000002000000000000000000008000000020000000000000100028327650e837a1200830ee326845ea34772b861696e667572612d696f0000000000000000000000000000000000000000000000384bddb484a40f7d075f5f909de4b541a315fcdfe86e1fe5f551d69cb36bc4f83c5f7d112380820c3da85bb2da4012f19aa2217451807d432cd5afc146acd3e301a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x938e9b131e45fff13dcf85c5d9092c022c2c9d56b2a9f1b6964fe9108d2dfd84","block":2581774,"r":"0xd6e0042bf2c88e31113d68b89fc95cd52c3ca7435493bf1dad92e11717dfc1d5","s":"0x0bc6eb2c905e1252ca8685d442ebcd378b0821f113d101e0048c6c8dceb12a23","v":28,"msgHash":"0x9d4fb41715fc086dea9426c32cd8a2b6e9bbd7b34a8472e43aa5e73c2f4f7358"},{"blockHash":"0x938e9b131e45fff13dcf85c5d9092c022c2c9d56b2a9f1b6964fe9108d2dfd84","block":2581774,"r":"0xa58cd2390dd3b445ecee134d47bf5abd999c7844c1d2f129276d1370c647e809","s":"0x0d3dd3c46705edbe0c7df345631522586bf8d26940b43e440af388db22edd0fa","v":27,"msgHash":"0x9d4fb41715fc086dea9426c32cd8a2b6e9bbd7b34a8472e43aa5e73c2f4f7358"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a0295192d3c5b49077c7f3af00d29f55c92e639cc87158f7fb495c0cf6dea7239fa0ee91ff68c120a29ed4bc36597af531054cbca3d75b7445645acf4ddf0d31f2fea04559125ed976d229dcd91af94b26ff81f85d52f5225e0757153df510651de93aa0c1fa9b27a600257d2d97d5121c34beedb1893bf0c115740db61109629e350548a08ad560283b1158f93c61b37749517dbdb6f1277146a3f7e79ebb5fc3eb126481a0c118bce6419906f8c23d0e412f03815cd6226a37971994950b20e98533309c53a0897a5883cd3e4d951238e6054d6b5caa32c281737de5d3d05f61ef3b9846a80ba04730f401144a9d532e7b427ce937b2b912214c405b1e3aeb2f37899dc1536d78a0b1a65a175a70a06673d4791ba45f9783b70a882fbb3d0d5b5f91227871a9cb14a030e40eb5fa2b10437c507e82c0682f5adc1ff250c8cec7c8d141b941400c9e9da0d7df4e91e8a643e3eab50542dbba095d4c3e2bf0dfcac15d20775813491c1269a08ce648317e9857ae16685367fd770b9854ab9af5ccf98a266b6fa1fe09746337a0a7e2d3e986882c76c8c63cdae33842841ec8bfa7c774c327cb01da86d21ff16ca05ce70f2d774dc6801de7c7a4c665af84502f58f8a492c67116a75824a8823b0aa0e50109bd6de7b045c859cdd578825ae4fbe8053e219dcf18337ed037e36e1601a07e4d15faf633af5d2d02f6558d9863fb858581b635dc6948018782e9b8088b9380","0xf90211a041103aaa4ca5ebb29cf3287410de9367720dade6381358f5605fe6201c1a5699a072a2bbfe83f4756cfc96f1f2d43aee5cbc457fa2be81a5dd7cb27bd434afd853a045f7df1d084faf674022712bdfa093d00eaf5a0cde0df976ea1b91ea9e4b53c1a0aafa71caf1579972c1ec1e3b3459f2e8337feede173ea8c056b5aa19a2df693ca066b43fcb732a6caee76a79939e5c1f2fa7983eff26bda2d087caf01594572d4ea0fb9af08296918cea43160b23ee460c8b13b910fef834d3761a1e9ab7dfcd87d8a0ea5a616a1a3c8668b1a0620ec135f0614b23b0e9191a19ae1eaeb56c645fa5d0a0b6baecbac90e0fcc76a405b35f0a4762fe45de34177fd67dd7f769e8907b69a3a01f98f4433aa0ddefa8e8ee2a73e3d3912f8b2182db688e25c25887bf8b546f6ea067752b356c29324671856eb921f091626dd699d891f7843682b71ad765d0520ba078556c735c76898f5cf1e27a6108837d1b2c8d6e92bcb977834a48c9277920c7a019d353880a2933b428fdcf3eb5f8f519b3347b7bfc17086b099976d210a92562a0a8bd7540aee53c82449c785e882bc5f1938e14673ab504373c970493f6168115a07de78c1db35d50b1a4712dbe972f8d84042e2099cbd56d45ba08060924c25918a083866d677646f27db8ba320e5e5a125f797c8421668c67c33e1cbc49f57663a8a038e0165ce0896e6b1e0b5d36d39f54c805a4a24fea87c7b233d385f6333c448780","0xf90211a0ddede8812030ee393d328cf0c91c82816c9f96bc0a66c1af65cb5f79b1637a25a0da3c2a7184e0f9aaddb6cc5a7a20d4413f5ec563e9f1761afea77e99dde4bbada084a53c667d75e65aa63d8cb04be9355b3b82ff081f715b6bc525435d3ce8f6c4a0840e71f98dfd18f63e241499c0eda112c083d493a75e5b357a328df4686be427a086903192ecd5128ec2283da7037ece448b7eef2ea0ecca0e4a2fdd3c14a1ed07a0a32ff45265b0c08eeaf2b2ba83cd4990f44c0e01eb99c7f86f3ea350b09fa385a06da4892c9eccd43a735e10974868099e36a51f728e9125bd7e1d33a9a9cfea8da043ed6ee56c0f506fb5dbe8be30a0bb4e0e1ffb6d2d5ac789f6dd798613cca8b2a0bd5569a2c29e66062ec91ba094caf99b5553053e81e6e2d3652e912cfba043eaa03a11de148e3a3e80be5112af4f6151918b7070230aedf3706cd9aa80cc258176a0f146ca9568124965eb8eea419288d2669eb061d3e4c35110bc8d0bc4e7fa4221a04067851f46b1aee36e281c8bb6cf4db12f28528a50f83fcd04c95c481b2b5993a07299cc91f3a668d8730a4af5b821e3082a4207e3cb880a296970fd5e3342d8fba0e0b46d93dcc1fda8b95f4161f384136d6d4913b3245fb227f58ab2411d97b6bea07286a0ad8952431a2d8f0e2b0a96938eeb9e498b6c588a8b03e70cacbe8fccf4a045be1f06062e86d7085b962d85ef562a8b22eb0e11457f0bdc29f8ad4209036e80","0xf901d1a02bbb5dda7a9bc9df45a8ac1bbd5bd0850902d193b56332a8c55150b214c8d987a071429682be3581068a0273a720de04ddeda04080fed8247881c526f68cc050e8a0bccaecb6bbb5eb8abbe6f835696e25ea86c8492943f0b754f6913baeedc1a9caa0a8677936e6b7f8e0c7abe8e569b3c9f739ac44e11e03cd3f37c0cf562cd98ad180a0b630e0ac24ec2b43a36c0c9caa61a4b5fa6ebb83294220fba97d415e8e770625a00cddc5c07dc61fcdd9ca75b7bdbed677ffdb077622f9142b71ba3f3ddb7fa9e5a0b6f6e28e039468dcfb64617d969bbe39047326276919ac13c4f4641f0ad475a8a03f74118689a48bc9f9682bd02abc86087f9966561b1aab25a898c6d04535c5d0a073163ac85225f8ba7a9a5dc6a42b062b85b8a5e5a5e38977c1f9890a5e6581c5a034d30b0b58bda0f4b5f3059e1132807678b0e7d0e6d303a31f24bc64dfea8dc180a0ac9e65b51107095a25be9c078ba1a134d7b185d8100e3f39016291328e434905a095c6fbddff1af3ee610bbc83fd48bc3eea0b725054aa1c4b616f08b238783ac5a021eaa5f9d89b8ad76a4898b1f8c58763a323bff30cbff1de36f3c7a288712cfea0e0b0e6bfa2a0b87c53eb9f6ca07afdb085a556bf78e047d98b32dbc287d6b13c80","0xf871808080a04666e3a5987e0a9cbdf1a330d25c6d3126319bca62404350775a62987abcca1ea0fc889a49c4876806dd6bf3dd10eaf1b835b5a51fb12565687461db7f5d2279dd80808080808080808080a0ebbab5b534b8863f30247c30489edf3a8bf157496db64869a46a3a55d3289fb380","0xf86f9e3a52bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c18885673694a100e8c98a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x5673694a100e8c98","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x18","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":2581780,"lastValidatorChange":0,"lastNodeList":2561644,"execTime":211,"rpcTime":105,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x5741bf83","in3":{"proof":{"type":"accountProof","block":"0xf90245a0f801cb62b5c7ef6a8837faed3abe76392fec9ab307f6282657534a52de0ad1e1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479403801efb0efe2a25ede5dd3a003ae880c0292e4da0a31a57f816e8f5677842a7be3d3a4a3ccd407f28c2cb6fdbab9e0dc9aef5834aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe840114b96d8398968080845ea348009fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8d200b841366bfe6412512cb67bff7b2ae6eb3b84a49e9b374005ac80bd7de5b992b7b32b57b551519e88e0f797b0032809d97a3044c22f58ad14b6b28b3c47a49ddbe29400","signatures":[{"blockHash":"0xd8af6eead33338f1a473c59891728c24883edb37e425843b293d746895963b7f","block":18135405,"r":"0x97317872ee4a0b7581ba732460b225cf60c43ed8fd6b0466341f8ba15e541c11","s":"0x07b91d88ccfbb3390e981e15cb2561dbefb0f028b85ff10dfc77c8bdd81de5b6","v":28,"msgHash":"0xdb86839e852bf1c6e855eb8c308724369cf40f82c0e26903e5760b5aa631ea67"},{"blockHash":"0xd8af6eead33338f1a473c59891728c24883edb37e425843b293d746895963b7f","block":18135405,"r":"0xdd27324f5c9760b7ee261c090ff78d728d5d483aca79db26443acdb63044b58f","s":"0x1d7307316cfb4d0d0353c2c7db107ca92acf6f58f6862a05b0ec29c4a7a8b203","v":28,"msgHash":"0xdb86839e852bf1c6e855eb8c308724369cf40f82c0e26903e5760b5aa631ea67"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a067fa22c0a627c31c4da9a73077733c3d28c971e36bfcbc88e2b12bfd50c92998a03d9433163e5bf4cdccf0d20cf873bd5a4925d85291d5dca30455c9e5f20d4bd2a08271a2425e7aa179634f35633d7cb69c91c33dab555af482998df9acb1a1215da08e8aea5e6a4a335852e8b3697c17872612363be199871de14f847da9efb450b5a0d674d3840e9066d2add2938b0866cb814274ba40f58b535db59894576949a66ea01189f4195a37e1b674d7da4316934fdc3f873a1da703b0a1565d806c4601fc8da05575868370ae9da68d2dd7b487e77929700653bcb014c65f44593ef87406f5eba011e3d5fbedd380c5b72dcd2f3fdcda49b77c89b128225fc3f10a63576896de6da08e28d242e4cc461c6792aa3c732fcc67610da10caf0916054f657775ae0baca0a035596268342fba4d966ab8ca56088c64afa7fd914e21549c4e6fd1a758924e78a03644ad4edc3136a68ea23cf8e72ba5468c036e5f624924e16d61d63d8fe5b60ba06f1132c7e3a56fb55bd742fd2a32e189366099f322cf1efe81c75acea0f5ec37a006f7af18a7b34cba861c480867de57867b3eb59d403c63f0bd5444800fe69043a0f80a4b3dfc7ed3af3ee6b1d0dc4d79b45f50bd71314a4d5d8cbfd14784e05cc8a0f77975cd7bc4add015ccf5dcd5e507e45ead242267c97ae3cf6dfcfb857c087aa0cac99a198fcc667b9957a901287112381e3705e3afd9183fa92f6f957f0712a280","0xf90211a0e11b032158349c1c888bbd1f00a221001ce6a81d8f88eebafa4261eddb0510ada0fb36f44116ca64f7e27e4e631b5309640e6ffe05798dca2e879cf0ef6533ebe9a08e49b32729ebb06ea9940d8fdc0dc30da57fe6b237e90ed7b265c957ad92973ca047d6edd574118393d63709f0505da850730003abf39261f2f9f91181781b021ca0180c214f4b424f127db7cd4bb93e8c2eb125b0c21c4b6cd1ef6f461defe473aba04f3e6f1a07a91b1baf470ef3d47e89ded264ff087521fe76b19aa92570606e04a015629e9486b37c4ea0a74c7f9f6437e37f0f7ee3c55bb23092c6bd02f20d734ba08dc38a2702942f93c499649919d5fb5d4403afa2ef88344da389802bc1215604a0797fc3246cf0d733f90238def8df0606b3f665e8d468d2c1c60585a0ade931e2a09e1d0e3431093f3d6d740b5a9131c76ecb83c3666a5a28777e5229207498ec27a086c9387e496b6cc608faa3e0b04716bdeddd66afb1cde152b2f53c755655c919a0109fd048a3a07a795181a66c986afa3ff98379f46b4a8e4bac2f1fcda50766b4a04bab50031a30d34954377d8080d0ebcf102d9a0b635d02b0dc234d78958fa973a09ff60acf48e0804d5ac0524c1405f2532a12395f6552fce4a99e8080a269ebdea0451bb84ab49fa321ba028b18506460de3fd005e70b5aadb78fb35aa995740fb5a01f1efca7e3e26eba186812b331350c91da25a00f37ccf20ba29e4fbe01eb332c80","0xf90211a0bcd4c7212d4f72ef3554fa846110e6e1008a0e574d206e7e6bfd4b59d43e1570a05c9a5c3dfb0e0a4eb57bca5e28632b8ea2a9b735adcd8ec9a9da8a45c9471439a07c518fa3ad1a00f6dc55d5c771aadb97c37c138a13c6f529ca6be8474ffb5d38a0921f8aa51cfce7f7b43d709e68bac821dab8a490374484a1cb26b955be8f7a49a03bf92e9f5da06713da0b065dd4e0b7755aff7e68f6242f945931567184d85fb8a07b168bcf5528078d49ba7f577b67629dd9ae1f1bfd95e2be5466bc6f96b781b8a01a188550197cabf1b723164292080f1e0d656a75a12c065ff913127b8e0ddbf4a0aadcdcc0dd431e6f38c150f2df063511dbba678399619f0d391efbb62eda6896a09940bff92764eb43cdf67872b82c11d2d77b2f1b380722a22979724cef04d22da0785796f2016d62881cef5562988f87249759dc937ef5f083cab0c9e56da12a5fa0e2cd369a9d99369b9d6baeb2763a535a89b84bfde74354dc8d1693751530ee14a053e87321f66f032595cf12d25e63e221e0cdc8b796cb402b00cdce176a9a987ca010ea1605efae6b73edc247c5802f11e77d56c4045c9a16a6dd18d956ef429234a0719e78dc21720cb95123a5fe60c5411e150102ef6c7b61a58766aceabde04c08a06fab10fccea1046ef3638fdb82d232f6a42d68a9a544b5cd019f52c5f7a02073a055fb586bdb716e8e1e15e293528a4a87a7dedb9b47223d484cdcec23a208425680","0xf90211a0fc37d7b4e05a26ebdc48d6291155b3dcb8e65e539b9eab3a4338928c97aaa1a2a08ae319c50a804c55300de43df2a3d1671e954bb24bc0853c81675aa6ca75a0fba0f28bd429ebcf25a504d2bbccb00dbd6014efedb9338dd014dd0b644e4594f978a003d0bb8239d96199784d55d30d69b48fc23da76265ff2b9c6b5ebbb0c9c0681ba05d66ee349662d4175dbd6aa43410a3f9d9b1cf93d0af31e7939e31db6df109a2a0923c62529d851072a71da0458c2a161cfaee1d5cc0904f10364d27dd60c06025a06ccb9cfecfba89c8c6f57ec92cdeea525d98148b536d975449583813744e57caa0ca8ac4e33b41d8bc34c493fb6d3f341bb0df9dd8d8bd6a96df6f1e4711ac9652a0dbca2b0de987b6af3b11e845260f033f67693fc7662d356d9e368a96cac57be4a0d8813c727a9e882c66573b81598b5ea686e5a02f163451c8e2fde31548c19f0fa0113e7f524025e88716441715fec60b05bb8aa46b7659f544bcf2b228eefdf550a0f3606e7bc1383b6e7c0cd5ccf2e72e015c0d38f5d53ac639d729636016e8441aa00f8ddca3dea3b030ca53377ec308b0d7d636f70cb43a03f244337947ba43f307a05afed7c112840f5f02712068987434819d820fff2a42c8b12debc210da718a89a0de942a1603bb17b26bc707dd99c305728d16b27808f8abeab822e91fdf08959ba033d4c1220e1f275d8728f2c486abf0579cacf99d228262e434b9533d4c87870380","0xf901d1a0d715975b1c7e735a7370af616c4cad7aae4fd47c7b580ebcee0663d69dac8f94a0eccf8b1e93f47afb46cb1f22724d6df19680c09058ab7bd977f740ec8df29842a04bf83792d9ea30df6e40c30a4c538672651d1d6dd9e8d32a912d37c2e281b08280a07300a78eecea1100c94057a6502ad3789c813426d52d054b89f5ab442edb8f84a010ec9d30d0d7293d2f0e4852146ca9630f3b5600e4cf6567c0283cc69f1a6222a0a88de4d81fbe04ee346c3ada2a42e7ac7694848919b802c3ccc478a2b8889993a0de183e05e8a90a0e78e9618b86eebdf7e95f41d7ad8bccdec255547cc6c292e4a0593036d0fd7daf9876ab33b96878346715ea258a00d4f42751310a12626bfa30a096a633e5335363e7f133af1f01d7b795df1dd16827511d841d1e7a00524d8bc2a0b387399d0e403e5dfbca9a9118bae1bfc8740de7a71d4dde38a4299db540878ba008d03dd61865f15b7000e8456a06cc37f64f9147ba588f1fef0936792e718023a0af02215811e7c978c2175ebd5abc4d40ed3defcd67ce8b74bf03c33efbaf5026a0e6e49bf2372d806ad6705278c00845fbc212bdac105eee2e45171e5dab2af0daa0a3d22ca0ccc92399e542043c70ef953f51eb0438c9cdcae487bbc4347080eaef8080","0xf851808080a0d0bcb8c586984b391a51cc43c60cf85579f0c11add716245186c53e21c14e417808080808080a0defa640aa5cf525e661aa1a9b42769c8fb97fc375572921ded2699dde8518367808080808080","0xf86b9e2052bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84af84880845741bf83a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x5741bf83","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":18135411,"lastValidatorChange":0,"lastNodeList":18098311,"execTime":120,"rpcTime":41,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x5741bf83","in3":{"proof":{"type":"accountProof","block":"0xf90248a0d5bcf71956ac6db799c62f79278727411b7009e12c3fd5255f05e4603806831fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794512aa2447d05fe172cf59c1200fba0ef7d271231a0a48190e6a781482abe927b75ea08d1c27fb5392081a8e43f311d94f964a44d63a0f1cd495d7a68241ce12f81fe746edd77c2b3bf875a66365437074c58a8de56ffa047d89f5617132784b8cf1e63e6335b6c89e3a54a495d83b116117b38419b5ef8b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000100000000090fffffffffffffffffffffffffffffffe840114b9708398705c8301ba2c845ea3480c9fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8d203b841e9d23fcfaaa3a91c561368408104bf0b8537ee8990cb26815c21853b1ac03f733aadde95e759735fe2670c2dc1077af9d715f0c7a25dca89d261f9043bb7137b01","signatures":[{"blockHash":"0xe18f44bd4160a5d9f747f5246ef15c676dbd806f5d88acebef6ca8a9a8a993c5","block":18135408,"r":"0x562797076cfe5d9fa3b5fc6b6877d6a7dcb6009eb6e75de3e0bd7dc27434e853","s":"0x7e5d527852e9220e6a24e6e42363cd687a0ed09c9bb03d0e0ddc62c7adbbcbfb","v":28,"msgHash":"0x84fa4fe60ef249306687274f2f28db8a4260f3a06ca0a66de1c5af719d98b4d9"},{"blockHash":"0xe18f44bd4160a5d9f747f5246ef15c676dbd806f5d88acebef6ca8a9a8a993c5","block":18135408,"r":"0x39fc90672f6b1613c54a70b99977e51e57f36ed8b080239a9b1e42d81a134246","s":"0x5c867fdef02501ed44641655828b22d12e5937fd4e30daea1604fa004d83448d","v":28,"msgHash":"0x84fa4fe60ef249306687274f2f28db8a4260f3a06ca0a66de1c5af719d98b4d9"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a067fa22c0a627c31c4da9a73077733c3d28c971e36bfcbc88e2b12bfd50c92998a03d9433163e5bf4cdccf0d20cf873bd5a4925d85291d5dca30455c9e5f20d4bd2a08271a2425e7aa179634f35633d7cb69c91c33dab555af482998df9acb1a1215da08e8aea5e6a4a335852e8b3697c17872612363be199871de14f847da9efb450b5a060163750d1eab696129bd22255805c489d6b15791a274d865d5fdf0fee70b688a0e78e651f6f733382013468ed1d3e221a0ea4754852c7ffe2ea70e60d1f023ccda06f0e38392ec5167860b89c655d857961e11684f31e7eb97a4a77ed5779da7370a011e3d5fbedd380c5b72dcd2f3fdcda49b77c89b128225fc3f10a63576896de6da08e28d242e4cc461c6792aa3c732fcc67610da10caf0916054f657775ae0baca0a035596268342fba4d966ab8ca56088c64afa7fd914e21549c4e6fd1a758924e78a0d74866a4af4dd57c3a589c457c1155ec8ffe573fc0eb4e8f4c6ab26dab1672f4a0f4f12bdcea537f20274b8c3304fc0dac78eda7dc0fb12222baae3925694b9162a006f7af18a7b34cba861c480867de57867b3eb59d403c63f0bd5444800fe69043a092d1b006eb3b27abfd5c92fbc40050bfbc1da255dfece12373fec3404d183760a0f77975cd7bc4add015ccf5dcd5e507e45ead242267c97ae3cf6dfcfb857c087aa05a38c7539b1dd6e7a6ce5a7d0eb51980da572a8c211644136efece518bb9484180","0xf90211a0e11b032158349c1c888bbd1f00a221001ce6a81d8f88eebafa4261eddb0510ada0fb36f44116ca64f7e27e4e631b5309640e6ffe05798dca2e879cf0ef6533ebe9a08e49b32729ebb06ea9940d8fdc0dc30da57fe6b237e90ed7b265c957ad92973ca0881009f7efe5b031480951f7d9c4e28fee7ac97e8e10d6174549a7c0ce744377a0180c214f4b424f127db7cd4bb93e8c2eb125b0c21c4b6cd1ef6f461defe473aba04f3e6f1a07a91b1baf470ef3d47e89ded264ff087521fe76b19aa92570606e04a015629e9486b37c4ea0a74c7f9f6437e37f0f7ee3c55bb23092c6bd02f20d734ba08dc38a2702942f93c499649919d5fb5d4403afa2ef88344da389802bc1215604a0797fc3246cf0d733f90238def8df0606b3f665e8d468d2c1c60585a0ade931e2a09e1d0e3431093f3d6d740b5a9131c76ecb83c3666a5a28777e5229207498ec27a086c9387e496b6cc608faa3e0b04716bdeddd66afb1cde152b2f53c755655c919a0109fd048a3a07a795181a66c986afa3ff98379f46b4a8e4bac2f1fcda50766b4a04bab50031a30d34954377d8080d0ebcf102d9a0b635d02b0dc234d78958fa973a09ff60acf48e0804d5ac0524c1405f2532a12395f6552fce4a99e8080a269ebdea0a42154860cf92395ae0d9cd8b0fff33b5c30aee3d2b5708f4c786c9fa7a2fc98a01f1efca7e3e26eba186812b331350c91da25a00f37ccf20ba29e4fbe01eb332c80","0xf90211a0bcd4c7212d4f72ef3554fa846110e6e1008a0e574d206e7e6bfd4b59d43e1570a05c9a5c3dfb0e0a4eb57bca5e28632b8ea2a9b735adcd8ec9a9da8a45c9471439a07c518fa3ad1a00f6dc55d5c771aadb97c37c138a13c6f529ca6be8474ffb5d38a0921f8aa51cfce7f7b43d709e68bac821dab8a490374484a1cb26b955be8f7a49a03bf92e9f5da06713da0b065dd4e0b7755aff7e68f6242f945931567184d85fb8a07b168bcf5528078d49ba7f577b67629dd9ae1f1bfd95e2be5466bc6f96b781b8a01a188550197cabf1b723164292080f1e0d656a75a12c065ff913127b8e0ddbf4a0aadcdcc0dd431e6f38c150f2df063511dbba678399619f0d391efbb62eda6896a09940bff92764eb43cdf67872b82c11d2d77b2f1b380722a22979724cef04d22da0785796f2016d62881cef5562988f87249759dc937ef5f083cab0c9e56da12a5fa0e2cd369a9d99369b9d6baeb2763a535a89b84bfde74354dc8d1693751530ee14a053e87321f66f032595cf12d25e63e221e0cdc8b796cb402b00cdce176a9a987ca010ea1605efae6b73edc247c5802f11e77d56c4045c9a16a6dd18d956ef429234a0719e78dc21720cb95123a5fe60c5411e150102ef6c7b61a58766aceabde04c08a06fab10fccea1046ef3638fdb82d232f6a42d68a9a544b5cd019f52c5f7a02073a055fb586bdb716e8e1e15e293528a4a87a7dedb9b47223d484cdcec23a208425680","0xf90211a0fc37d7b4e05a26ebdc48d6291155b3dcb8e65e539b9eab3a4338928c97aaa1a2a08ae319c50a804c55300de43df2a3d1671e954bb24bc0853c81675aa6ca75a0fba0f28bd429ebcf25a504d2bbccb00dbd6014efedb9338dd014dd0b644e4594f978a003d0bb8239d96199784d55d30d69b48fc23da76265ff2b9c6b5ebbb0c9c0681ba05d66ee349662d4175dbd6aa43410a3f9d9b1cf93d0af31e7939e31db6df109a2a0923c62529d851072a71da0458c2a161cfaee1d5cc0904f10364d27dd60c06025a06ccb9cfecfba89c8c6f57ec92cdeea525d98148b536d975449583813744e57caa0ca8ac4e33b41d8bc34c493fb6d3f341bb0df9dd8d8bd6a96df6f1e4711ac9652a0dbca2b0de987b6af3b11e845260f033f67693fc7662d356d9e368a96cac57be4a0d8813c727a9e882c66573b81598b5ea686e5a02f163451c8e2fde31548c19f0fa0113e7f524025e88716441715fec60b05bb8aa46b7659f544bcf2b228eefdf550a0f3606e7bc1383b6e7c0cd5ccf2e72e015c0d38f5d53ac639d729636016e8441aa00f8ddca3dea3b030ca53377ec308b0d7d636f70cb43a03f244337947ba43f307a05afed7c112840f5f02712068987434819d820fff2a42c8b12debc210da718a89a0de942a1603bb17b26bc707dd99c305728d16b27808f8abeab822e91fdf08959ba033d4c1220e1f275d8728f2c486abf0579cacf99d228262e434b9533d4c87870380","0xf901d1a0d715975b1c7e735a7370af616c4cad7aae4fd47c7b580ebcee0663d69dac8f94a0eccf8b1e93f47afb46cb1f22724d6df19680c09058ab7bd977f740ec8df29842a04bf83792d9ea30df6e40c30a4c538672651d1d6dd9e8d32a912d37c2e281b08280a07300a78eecea1100c94057a6502ad3789c813426d52d054b89f5ab442edb8f84a010ec9d30d0d7293d2f0e4852146ca9630f3b5600e4cf6567c0283cc69f1a6222a0a88de4d81fbe04ee346c3ada2a42e7ac7694848919b802c3ccc478a2b8889993a0de183e05e8a90a0e78e9618b86eebdf7e95f41d7ad8bccdec255547cc6c292e4a0593036d0fd7daf9876ab33b96878346715ea258a00d4f42751310a12626bfa30a096a633e5335363e7f133af1f01d7b795df1dd16827511d841d1e7a00524d8bc2a0b387399d0e403e5dfbca9a9118bae1bfc8740de7a71d4dde38a4299db540878ba008d03dd61865f15b7000e8456a06cc37f64f9147ba588f1fef0936792e718023a0af02215811e7c978c2175ebd5abc4d40ed3defcd67ce8b74bf03c33efbaf5026a0e6e49bf2372d806ad6705278c00845fbc212bdac105eee2e45171e5dab2af0daa0a3d22ca0ccc92399e542043c70ef953f51eb0438c9cdcae487bbc4347080eaef8080","0xf851808080a0d0bcb8c586984b391a51cc43c60cf85579f0c11add716245186c53e21c14e417808080808080a0defa640aa5cf525e661aa1a9b42769c8fb97fc375572921ded2699dde8518367808080808080","0xf86b9e2052bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84af84880845741bf83a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x5741bf83","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":18135414,"lastValidatorChange":0,"lastNodeList":18060209,"execTime":132,"rpcTime":36,"rpcCount":1}}]',
+ },
+ "eth_estimateGas": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":"0x55c8","in3":{"lastValidatorChange":0,"lastNodeList":9936896,"execTime":108,"rpcTime":108,"rpcCount":1,"currentBlock":9937265,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":"0x55c8","in3":{"lastValidatorChange":0,"lastNodeList":9936729,"execTime":831,"rpcTime":831,"rpcCount":1,"currentBlock":9937266,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x55c8","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561645,"execTime":46,"rpcTime":46,"rpcCount":1,"currentBlock":2580783,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":"0x55c8","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561644,"execTime":48,"rpcTime":48,"rpcCount":1,"currentBlock":2580793,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":"0x266c6","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18098311,"execTime":274,"rpcTime":274,"rpcCount":1,"currentBlock":18133643,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":"0x266c6","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18060209,"execTime":73,"rpcTime":73,"rpcCount":1,"currentBlock":18133671,"version":"2.1.0"}}]',
+ },
+ "eth_getTransactionCount": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x9","in3":{"proof":{"type":"accountProof","block":"0xf90215a056974f8b25a3ad45a970aa95af0bbb39a848ecfab96714a62f22b90f138f067ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca0c53deb778725e557247d4cfc07eb97ce3f77258441db3b07e444f521c3fd33eaa0d4faffcdc6a3f8b79292cdb45d55438ecbb0040d206789aaf5bcdd5b89a9fcdca00423d296437f7fa53e025b85a53a95677b0cef54804930c3a03d47e47f13c96ab90100918481002442304c48b183006414d861939c5a085f9f42946100064000ba4f865200a0d0a228643294950242be02018033628a0a08ab340202d32285f128ab4650083033c400e7636e96f8182080f70606024b28350a6e32626030a1a202f301da2c056023660022410c544006889c20ac253a9d1680109d2a382c913422b029810935cc04522541501282a002214bda84302db9e902f5c440044806823000148f5e60100c2070222d26d086fa061f9e1283c49184405bc1c5d10680401014613030ac82e0867f9288b222926800a215640852cb60a6289c1040109a541b6184a0183558bb20f21c0c098290c35e0af401800ea80206b6d0005af4247e913d6c8707f7d5bc55e75b8397b3b68397eafc8397a1b5845ea43c7894737061726b706f6f6c2d6574682d636e2d687a33a0bb0ea2cd56bd317d30647fc5af8cc92460b9b67540826b44e1a97388109f2a6f88f82fb9340d1c7e53","signatures":[{"blockHash":"0x5cd9f439b0a5e4e52a6f1a0f127dfef92b3471f91480fb88506e59835a64d395","block":9941942,"r":"0x3cf4f2e34064335abee3fdc053646bc8e40c9595e6861bb3c093011b8bb9948a","s":"0x4cab5ff0dbfe25c03a26d18b0132acaa3634a96f4b99420943eeb15760f68265","v":27,"msgHash":"0x78eb1922e1be17af9c668b36504b5640c9a4f479a50d679921efc5527ca701a4"},{"blockHash":"0x5cd9f439b0a5e4e52a6f1a0f127dfef92b3471f91480fb88506e59835a64d395","block":9941942,"r":"0xc83746b8db05d2f1ea78d038fc3ae3285c1e0b4441ac9fb9f92a563486745ca7","s":"0x122d01ab8f4615d42cd583cc041f837b806e2ebeb499f952a1b829567c27bca8","v":28,"msgHash":"0x78eb1922e1be17af9c668b36504b5640c9a4f479a50d679921efc5527ca701a4"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a017973036bd982783c4792cf04d92c1809ca159e18034a008d80a293460491908a07c15e0fdd027c54e3f8ff6ab6b98c3d8607e198242457b7c1db26866a72b26cda020ec69abbf5f8244ecd8d3cda760c529dcea37451a672f89af16134cdcd8dcdca0b02dfb95031f9890ef059170532ea3c7e3e34ccd6d56063207ffbf01a2f32e50a09320459026bc2c733de08924f77a4cb9e43a21411aea0863249617f38356c7a3a08377ecb5bca6aec00dc926ccbf7e51ad5c028c2ed764da99e2c97602a230ff8ea087c3e18654c351e8d354d1406160ff925d649002aa71aaa93dfcbe2f84d9433da099f6db4ea03a30a38134551b9d7c979e71a910d52bcafedaff472b4ef95165bca0579b8ac19ab4277609dd1494b8b77bb94264fe50c9d8f4ccef132344f104a14ca0184b0de00bc21fade87fe6f7cded08db847b8faca9d7795d423f34b3f931e48da003d924507be58c11c90319abb459ef15a011383caf6da984130aef6bf105be7da08ba10a7d7d4378196db774e5ba70b98cfc9a2634439128e628e63226aac1add0a03c4f3e9a6376d55beb4a92d8275545bfc89089a3e35be8d8649558890737fa1ca01224be6c84d1a01c7c38722f99f41a201555f1beefba0855b112b6e33f23c1a8a0fe2435663e36fa0e37a2d046ffda52ac108936b32e308b6b6536ac1e0f0d8fb0a0b5eead95069901211559a0a7f9d5504b0f927fd7f31c3d6e1715f08bbd3257a480","0xf90211a0cf4c4a3ac76d0165d86a81c9153666b7daf62b0fd71e2cc5e4135b4452b342f4a0736d52daa752859316b92a55f75ffff4b86b1bc8a0bfb185b8d53de14ecfe493a0da26eb1214e4c47cda45d36d5244c08a5be09466c8def8483894064451f319baa011085e10da4f49b0cc5ab6fdac73ced0b1e9c1dc544d27b9f48eeeafa2d91c15a0c82df6f1d1a0ab4634a9f24632fe1363547cf5a1a9064011bee7f492abdf37d1a00a1394b25ff4da3f1cb33c533a011b3af529a8ee1067379f919360c710944931a0151eca6307f804269f122ad2b9186224250126de70538dd4499a3395bbdbcf21a033bedebf38b5fb7d854c732c3a3c45e75dc1126013da5e97cbc2e38426b490ada0d2dd9366e58429e07308b76bfbf88ee22ab5a811074dfc186f4196122bc8dedaa003c86747398471980d3add51a1fb9d7af58955b4a521bfd879afb18bdaca79e6a011248430e8c979dfc73fe7296259d7caa4f9078cb2403d7a17b6470308012721a0238e9688463e52c1ef7a57fb6a225df17ec9b5691a5f4aef01f500f3a516fec8a02c742053d734d56c7165942c088410a9d6569d61962da7e0e8b9ee25a3e1ab01a0c892fb1a52ce0f006c35bc0c818dcf21bfb0848e72e7283b9b0de267023504c7a0c59c51aa5f584ab27c8c3e7b58acf930b2d1b0da9ad350cde3fc87b51ef7c4aaa0f94d374e3ba2bad70ab72013b6eb6b9fc758dabb9d2094caaa96180b1da094d480","0xf90211a0833ba229990e7836c6e3cf93b272e01318db2ddde22d45f50b98d85b4da168bea0ff107c7306c29d23162932d3214a074a9062250eefba3f11aa219c49074bec0fa0af9f5feaeea3f5ecae7b9dd061fb99f0006323abd05d753bd6c066b8c3073fb1a00a83d95f8cfdc210dfd21518cd163ae669789dfd7f66eec5de98f97abc3b1ebba061a4d294a1771f75dd8204fb8fd4f7c30266f2b6cfd14fdc64051593d48f92e6a0a9e456c6ed5c50faba4d162f09dd9daa6e28245aacec509b07e6eca32ef238b4a0126ecff07154b721da399907f143692155ef6ab4e40e6941e1ddd92cd4aab1bea0153bab83076a754e3685f19c1542149e35cec0260adbadfa24ea64d718adb1f0a0ffd4886eecfbd9f4843fb7bc3953b499c2cb6484cb43af2e4060757dfdf63232a062f3ed875f94e075f66d5f77fbf238a557293a3c4a333610ed05ead01608f59ca051b5ee182ae8046a0397fcb86d5f9e3f9d27f70e973ff1f536b9163ea0cb204da00a5cece9fcc41377d691071951dfe88932fb934e710527d803e3def08b71e7b4a0d3cbae0586911fd7fe23a989e8ee0756c2c9193faddc79f2f98f48e8c94ca862a09a223d82ed04ba5ce37d7d82fa2e9385c430a35157185e896d9827d20c5cc71ca03eff5a0ddadebd74ff9b069ac5cccdd535e8d9b1505a528738b6ef1ec619142aa0d21265978b6943ba3be215f83ce1026a0c878762fbbf244399d9117da225210c80","0xf90211a0a558febf61c70db0c8f6c4196409862d5450a6e21646bac1d2788b1e18e746f8a0a682cd5f9a1173b8e99e19c9a7cbe1f33c989e39ecf29a4e99128c5e661ea597a0a11a05fea0440642e10a60315ae9d987d35d603f3fbf70ef95432b3ef6f205b5a0c02cbdccebf63518f17e3281b636f3f8f27c55a5ea6b3d60bab72141c5bd9f4aa0e1ff4982be8e194fe6eb4b7792d692e5567da36231202ee0c7d8429e3d224baca0cb63862fa960b841f23f9f74b6bb8d18035b05598a099203e97e3a34a534bf7ca007bbe14417015ea06ceac5d64ba2a6cb97dba45f2aaae4e06a1a6a2cfc97b572a0c5314c1c21da8661da2495657fa0d7da3ff0080e6c1d973af25f9c3694a4eb51a05b75ccc71c1f7876e794a91e474a7a0c114eb0e1b5d7cd958cc7a24a0a27d9fca00f21677070f57a9d42f2ecdb00e1cacd197df3804873c1d3b0c6773476a2b885a010aad79059a3882c9778b12e2b10fb5f0e6775716f6e7b789e78e8ce18f9a881a034c63b424337be9f8796faee518af20a63129b3b5ae08e888fcc5969df722dbca030f12eab739830cca93ea98ecffa2b41a3bd3fcc6510b3837db44d5c03e0e6e0a0a4677fe1a87e950fe89104e450e2336146910ebd08accd5f7a843af5d28bb8f9a05943ed7e1c473b069922a0f83d7a5e12e4d549ff8c3dc841646c7af51053f3baa005e7db1c6e24dac7e4b5f6051ed3b23ceb4ed18dae1ff8271d0bf65e9e9df0e380","0xf90211a0526abf27762a1e6a760b996f275bcbd3e8b0385f8b1a4f7d6e287afeee3e617ea0d70b6811a39084c31a0844d992fd1d1333ae871dadf570b115804e2e44f8fc80a08776484be1c12cf5369099e303761867b5dbeba8fd3d181f0f2e8f0005fa0b80a08c11c55944ee7cf9588f541615eab7de3b980b888aab1328317fd0ce619bdc00a0f7250d86a51c5795f540ea18eb4ad13cafb76176f451c39fc813e225c9ae541ea0655bf907f8fd977e5f201586831caf0cb60619bce9a7d95ee560e07b63b8d4d6a02ed85b49cac72581fefa75f224b954f638fd3c9fe5de10b2ebaab520276fdbb1a056d21124e2892a9ebbf0c3268960c618884704c774ee721ac339c5c9c0ce19f9a064ff7aa541719eec43608cb72aee413850ab4031c2e1f2e18138013f0dcc292ea0e788fef800fa31cddc1f69d4daaad414bab802f6688e42155bd91182f1b4ebe7a037df45442419a2c54e69e2b4e69360720823a8151bd8be982a2cd355790235daa0de135dd855f549fb56c0a1a1859e2d2fbfdb9bab664d407fb16d54a282fc28e4a0ce4600309c4ea2837c39cead22af139d031c0636bccc8857289d6ab8658df475a0a0c92f9d83487592f5084640e85514dc014b7752e964485a79c7bde3af6f061ba02684be44f2cb6297191d5a558e68e8a6a7dd33322d16f581a8e4f5879336dfc7a003df4a92433942162081143bff298f5be3f0ea31eee86fdb1585f974acc80b8080","0xf90211a0222bd237a2d10e712e2c86d9dac5c8a7c5985c5da958d1fd6142b37ea18ec707a01095094b5e902b686060bc62e4c9d7103d31b7dd4cf879fdf6cb036bd83add67a0d0bf92f6895986dcd82fb0563e9d9c5d14f37e05ce053ddde9c7e9c7fc30c2c6a0f37181ff7a96c723ba931bbfb0db1d37d3752ad7bcb792a2f3c9d691ba475d99a06278e87f0456db8f07030794cd555fc0f47cf333a8a7a2cd47380963f28ab4b1a009e805e5034c070465498496ccd8c9926e134896cbbe6142ec3acea3052ea373a0d1d843eaaaaeef9cb88e9f1bf8ef9e29e14273ea86fa4c5274a686e322ba7f91a0acd7a6879246a65755db29b5fa1406990f401e31ccc0363a80c44637a567deffa039f9645da32ab327f07a72721794a2f141fb1723f3f6027ec84e38a15a539fbea08571667ccbbb5cfc39019c8a7990beab1ed3a62074cfb6030e434f1a27d17adea08431028a6676835999e614a487f27f8e15b6723e4d017d01bb6401bcada0deb6a0858002a1e730f328f3f02b99871f6c469515068b601b47dc15cbe0d9b1d5fdcfa0baa3fa271fc8c381bffe19e0b81401df254d6f305f3ed243d96deb3cdcc170c0a01804356e51098c03da7dbfaab03b899918de0cc79a30350a560380e1d5cc153ca0ff682943d177c894e7d079529bcd4053b20fe9c3f4a20afe87694b1d820a7a6fa05a64d0fa6afd9fe7705a93e9a6642287e87e699907b359d9c60de6630e9a5ca880","0xf8b18080808080a06fb8f6c9a850c201150954e07c9ac23b0ceaaf625cf8a79a362ecb5a55ac4e8ca0a6a3119e34b9242fb240c2a5c4fadf556f9bf8908bb4b411e63f52b8030d62fd8080808080a068ca5cdfb862ff949e832afd5f5031674bf756c03e6eb33485b3c0814b08b2b2a07fa66234a8621a311dcea5dd718fb7b35c90df669bbae61d2f8c5c1f8e439150a00c7b0ee28b5dce8efac5964ece41b3aec29ee10d5243085e3448301ae111d98b8080","0xf86e9d32bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c098801a65c39b274fefaa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x1a65c39b274fefa","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x9","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":9941948,"lastValidatorChange":0,"lastNodeList":9941433,"execTime":212,"rpcTime":94,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x9","in3":{"proof":{"type":"accountProof","block":"0xf90212a0bbf2a300e2224649d51e8eb63546ae2f4091fd71a69322360c64efc04540e338a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a0d9277f3e9d38b4806dab6a72bd2d2a36e0cdae72b81bb1a0db94a69af0d3d756a0f4e567b4d156a1607da63da2eaa506bfd2ff20aebb5f16bf2518c63d771e057ba0fd9a4372de25d6150699e01592a321ba29547ba167cecee419a5afb6ad5d5b5fb901000532180211000800000004002020000a12064c12164010008805021018000001c1050000e40808010010100000021900021020501008220200011000502ca124140000200008c4031a040d08018040a40200900040482250000410804a00220050a0024022000000020020842828080802001223088641220a2044314000008801002308000000004240808000148300900605100900900e811000628018010003d400108444e088800001871021840200002010040040408404002030401040020b0802200200800308005104000070004014030086020990400040000020140010009805001080040a0040000488000028001101b02a0180000900028060088707f5d7e6c62a548397b3b98397fdfb8397faf6845ea43cad9150505945206e616e6f706f6f6c2e6f7267a02a9c7e5d4f878d0fdc40bfd328ad44b143161fe88c36b68b715530c78d0b473f883904a63006e7277e","signatures":[{"blockHash":"0xea3993123bd65872bb437af2e4dfd19c3561c45a86a4eced6d5e4f54a0963dae","block":9941945,"r":"0x2015c6505c378d99c8dadb6c9d359ef52f315a0d0fc25a90efca18fd9290e71f","s":"0x18314c9b5ade4762cdf881cbfcfde8d61cd389a5b59168be196b2a8a29bae147","v":28,"msgHash":"0xbc8bad5b6a9965bb65ee1b91b3b369f51fc71c253084ad5994894f5cedf6e595"},{"blockHash":"0xea3993123bd65872bb437af2e4dfd19c3561c45a86a4eced6d5e4f54a0963dae","block":9941945,"r":"0xd37cfabd652703b5188dda195cdc20759db31e9a682740b169c2e8dd5c195129","s":"0x0364cf073c2580640f0eb0471b41341147732027a4c2a87f05297c5b802de3f8","v":27,"msgHash":"0xbc8bad5b6a9965bb65ee1b91b3b369f51fc71c253084ad5994894f5cedf6e595"}],"accounts":{"0x6FA33809667A99A805b610C49EE2042863b1bb83":{"accountProof":["0xf90211a09aefe7a71b15d17554f5d5d453e1675c6af8e12273331e66717f80ec7420aa06a0e298cee4cf227eb380929c1353c6bd6ced714a094d2de2623922fb75936c4d1da0cf5c3f8a82f59b524ce16089af0e36870a9a99ebd30560d8cc7b9d536d81b04da036c92b3fbda6dfde003c81c3f5038a601f34f375de9a6221852e50272c4f6bf7a0e19cc42955fdcf2649dac40850130bddd01a2de3089e5280cf8798dcfd965216a002cb5b41b64d985eb25c99532498de00b7a40df27a0739a87fd499e0b47da5d5a037fb79375f61e7869084cd048f1159c7ff1cd835dabea522017d4e6502effb67a02bd34d2162e30bf190243ce22a2c618ef5243926258d0acc22dc0db1ea322608a032c1ce9012589b67c8a487754551262bc015e7d703995998a0822eb6196371bea04b958c6f1ddefe56912eb9dde84e89e62acb436a8365cb7ad2f3498eb29e7c63a0647f6f1cbc01583c11066df4bae3684e6c2af59b3708fb9c950481e13257b338a0e2d342d5284337852ea74e5d3a2655311fe8bcccd1c934c2e070051066b37925a0ce3934ab759ff7d62ac3a9d878c3bac0ecd81d34e1256de4f3fc7c4cffc5dc1aa087185d55e717305a44d835d708b5f12de9a101f0bb592246fee724f982a794b3a0aebc468de976349405c1f05850b1c3f510fe183554feb72dd8080efe69b838cfa0185655e682db599b53453ddd12c6453e283eba7859c110eb3142d16141b95ef780","0xf90211a0ccb2b1847366a5760ac32cc2b11d12961e615820d90d988e7cbf2c9f03a10263a0baed7f68c8ce543937a7d9ad7d59e9bd6231300785a48dbd750d0b3125521d7ea0df5f43901aaa22e430bb757a8df84e1c334e3656a7b3910da4b40f11f4845528a0009c8a6e395430ca7ee5081155d859a0e617a13f4224cc0287c342707c4c32bca024eeff2ef966cf6884bc58991996ebbfe02cc52a2677b00cbdcc7e7b93fd2feda0c9fba123228c1c8148595d2dff5bceef07988be8bdf519956251664f4e373699a093432d156d0a1305caf27b81c50a6a011c6fd71a3c0b8f065c6461d4c9e0f2f7a033bedebf38b5fb7d854c732c3a3c45e75dc1126013da5e97cbc2e38426b490ada03d7390e2994f833ba4d9c9f607a20e7c850db08e2a6952ee0ad339cee836d0d7a08b0405c79c35798aad5ef9c380bbe51aca21aa7af46bef45acd1fa1e64110fcba06602ef9b5216a401275e19357666645ad0649e42fa78bc42a0715b6a83cd1f81a0d349c1d4ce1597f27ac7d4ab7911a215a8c9297846cb130ddb9149154a0882d3a0fbf2f75688993a250f510c91635034fe63c38dbae5d528c0366250dbb1b7a7fda0955fb4c84225253fe0a9b9191f3105906e56ada83c4cebef5ccf66713d78fafda0acd5adfcce8403565f5341e9bfde4d70cb6b4d4a19d3c42de31108a9e10d7df9a00369021bac3c9641739f8c02f9169bb7cef65015fd5808a070ebc9760792774980","0xf90211a0833ba229990e7836c6e3cf93b272e01318db2ddde22d45f50b98d85b4da168bea0ff107c7306c29d23162932d3214a074a9062250eefba3f11aa219c49074bec0fa0af9f5feaeea3f5ecae7b9dd061fb99f0006323abd05d753bd6c066b8c3073fb1a00a83d95f8cfdc210dfd21518cd163ae669789dfd7f66eec5de98f97abc3b1ebba061a4d294a1771f75dd8204fb8fd4f7c30266f2b6cfd14fdc64051593d48f92e6a0a9e456c6ed5c50faba4d162f09dd9daa6e28245aacec509b07e6eca32ef238b4a0126ecff07154b721da399907f143692155ef6ab4e40e6941e1ddd92cd4aab1bea02ac82954d5da719a0fc54faf57cfb96f04a332bda55a4ac5e394812caf12d49aa0ffd4886eecfbd9f4843fb7bc3953b499c2cb6484cb43af2e4060757dfdf63232a062f3ed875f94e075f66d5f77fbf238a557293a3c4a333610ed05ead01608f59ca051b5ee182ae8046a0397fcb86d5f9e3f9d27f70e973ff1f536b9163ea0cb204da00a5cece9fcc41377d691071951dfe88932fb934e710527d803e3def08b71e7b4a0d3cbae0586911fd7fe23a989e8ee0756c2c9193faddc79f2f98f48e8c94ca862a09a223d82ed04ba5ce37d7d82fa2e9385c430a35157185e896d9827d20c5cc71ca03eff5a0ddadebd74ff9b069ac5cccdd535e8d9b1505a528738b6ef1ec619142aa0d21265978b6943ba3be215f83ce1026a0c878762fbbf244399d9117da225210c80","0xf90211a0a558febf61c70db0c8f6c4196409862d5450a6e21646bac1d2788b1e18e746f8a0a682cd5f9a1173b8e99e19c9a7cbe1f33c989e39ecf29a4e99128c5e661ea597a0a11a05fea0440642e10a60315ae9d987d35d603f3fbf70ef95432b3ef6f205b5a0c02cbdccebf63518f17e3281b636f3f8f27c55a5ea6b3d60bab72141c5bd9f4aa0e1ff4982be8e194fe6eb4b7792d692e5567da36231202ee0c7d8429e3d224baca0cb63862fa960b841f23f9f74b6bb8d18035b05598a099203e97e3a34a534bf7ca007bbe14417015ea06ceac5d64ba2a6cb97dba45f2aaae4e06a1a6a2cfc97b572a0c5314c1c21da8661da2495657fa0d7da3ff0080e6c1d973af25f9c3694a4eb51a05b75ccc71c1f7876e794a91e474a7a0c114eb0e1b5d7cd958cc7a24a0a27d9fca00f21677070f57a9d42f2ecdb00e1cacd197df3804873c1d3b0c6773476a2b885a010aad79059a3882c9778b12e2b10fb5f0e6775716f6e7b789e78e8ce18f9a881a034c63b424337be9f8796faee518af20a63129b3b5ae08e888fcc5969df722dbca030f12eab739830cca93ea98ecffa2b41a3bd3fcc6510b3837db44d5c03e0e6e0a0a4677fe1a87e950fe89104e450e2336146910ebd08accd5f7a843af5d28bb8f9a05943ed7e1c473b069922a0f83d7a5e12e4d549ff8c3dc841646c7af51053f3baa005e7db1c6e24dac7e4b5f6051ed3b23ceb4ed18dae1ff8271d0bf65e9e9df0e380","0xf90211a0526abf27762a1e6a760b996f275bcbd3e8b0385f8b1a4f7d6e287afeee3e617ea0d70b6811a39084c31a0844d992fd1d1333ae871dadf570b115804e2e44f8fc80a08776484be1c12cf5369099e303761867b5dbeba8fd3d181f0f2e8f0005fa0b80a08c11c55944ee7cf9588f541615eab7de3b980b888aab1328317fd0ce619bdc00a0f7250d86a51c5795f540ea18eb4ad13cafb76176f451c39fc813e225c9ae541ea0655bf907f8fd977e5f201586831caf0cb60619bce9a7d95ee560e07b63b8d4d6a02ed85b49cac72581fefa75f224b954f638fd3c9fe5de10b2ebaab520276fdbb1a056d21124e2892a9ebbf0c3268960c618884704c774ee721ac339c5c9c0ce19f9a064ff7aa541719eec43608cb72aee413850ab4031c2e1f2e18138013f0dcc292ea0e788fef800fa31cddc1f69d4daaad414bab802f6688e42155bd91182f1b4ebe7a037df45442419a2c54e69e2b4e69360720823a8151bd8be982a2cd355790235daa0de135dd855f549fb56c0a1a1859e2d2fbfdb9bab664d407fb16d54a282fc28e4a0ce4600309c4ea2837c39cead22af139d031c0636bccc8857289d6ab8658df475a0a0c92f9d83487592f5084640e85514dc014b7752e964485a79c7bde3af6f061ba02684be44f2cb6297191d5a558e68e8a6a7dd33322d16f581a8e4f5879336dfc7a003df4a92433942162081143bff298f5be3f0ea31eee86fdb1585f974acc80b8080","0xf90211a0222bd237a2d10e712e2c86d9dac5c8a7c5985c5da958d1fd6142b37ea18ec707a01095094b5e902b686060bc62e4c9d7103d31b7dd4cf879fdf6cb036bd83add67a0d0bf92f6895986dcd82fb0563e9d9c5d14f37e05ce053ddde9c7e9c7fc30c2c6a0f37181ff7a96c723ba931bbfb0db1d37d3752ad7bcb792a2f3c9d691ba475d99a06278e87f0456db8f07030794cd555fc0f47cf333a8a7a2cd47380963f28ab4b1a009e805e5034c070465498496ccd8c9926e134896cbbe6142ec3acea3052ea373a0d1d843eaaaaeef9cb88e9f1bf8ef9e29e14273ea86fa4c5274a686e322ba7f91a0acd7a6879246a65755db29b5fa1406990f401e31ccc0363a80c44637a567deffa039f9645da32ab327f07a72721794a2f141fb1723f3f6027ec84e38a15a539fbea08571667ccbbb5cfc39019c8a7990beab1ed3a62074cfb6030e434f1a27d17adea08431028a6676835999e614a487f27f8e15b6723e4d017d01bb6401bcada0deb6a0858002a1e730f328f3f02b99871f6c469515068b601b47dc15cbe0d9b1d5fdcfa0baa3fa271fc8c381bffe19e0b81401df254d6f305f3ed243d96deb3cdcc170c0a01804356e51098c03da7dbfaab03b899918de0cc79a30350a560380e1d5cc153ca0ff682943d177c894e7d079529bcd4053b20fe9c3f4a20afe87694b1d820a7a6fa05a64d0fa6afd9fe7705a93e9a6642287e87e699907b359d9c60de6630e9a5ca880","0xf8b18080808080a06fb8f6c9a850c201150954e07c9ac23b0ceaaf625cf8a79a362ecb5a55ac4e8ca0a6a3119e34b9242fb240c2a5c4fadf556f9bf8908bb4b411e63f52b8030d62fd8080808080a068ca5cdfb862ff949e832afd5f5031674bf756c03e6eb33485b3c0814b08b2b2a07fa66234a8621a311dcea5dd718fb7b35c90df669bbae61d2f8c5c1f8e439150a00c7b0ee28b5dce8efac5964ece41b3aec29ee10d5243085e3448301ae111d98b8080","0xf86e9d32bfe60095ddcd84f034725c1bd3d0927486bf40387ee28e3cb14ad7ecb84ef84c098801a65c39b274fefaa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x6fa33809667a99a805b610c49ee2042863b1bb83","balance":"0x1a65c39b274fefa","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x9","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":9941951,"lastValidatorChange":0,"lastNodeList":9941433,"execTime":126,"rpcTime":48,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x7","in3":{"proof":{"type":"accountProof","block":"0xf90259a008e105408f4e4fae8b4012130707bed169e5ca5a5156f77a23546627856c58a8a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0bcc2eeb45961f9495149f9dbab5cf8e939f69423365786fad8c6ab99b5225c08a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832762be837a120080845ea324c0b861726f6e696e6b61697a656e000000000000000000000000000000000000000000c18297b7891edfcbe5e291dd2e8dc1be63af0837c47df8f567eacc2588acb2df528821658152767f1b3ea1a6d9d6fe534abc3356daba5cb0586e7b411d24559c01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x18efce2c577f5d0bd6b433bcd6ebd01e16e24025387139270b09e1d1466476e6","block":2581182,"r":"0x000a080c021731e821676d76275d61f5c73a224109ab52d740bab627a52a6b1b","s":"0x7e29671145b97d70a0a32492f62b28ed53d0c9ae4de485919b8028f97815f9ef","v":27,"msgHash":"0xbc1aea8ad7d72e61f98da3bd7d3c2f2bfe091cf309953fdb3368531da5b1660d"},{"blockHash":"0x18efce2c577f5d0bd6b433bcd6ebd01e16e24025387139270b09e1d1466476e6","block":2581182,"r":"0xa23f1b35ec7cd213b43a015985c80bfb74046c2d06af99230f3cd13bcc72b592","s":"0x227daf159f49c3f4b936dae34759a4834b71887b40208343e4b8129c46c1f782","v":27,"msgHash":"0xbc1aea8ad7d72e61f98da3bd7d3c2f2bfe091cf309953fdb3368531da5b1660d"}],"accounts":{"0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308":{"accountProof":["0xf90211a03a63400d749fd0ccdbdda979f1a612c34eeb8d297626dbefe24c65a5d02cd169a0a0e0c5a6ad9fde9edc05dd8f3b354ed398fd0929adef1afeaf9531c429bc8759a0a709646bdac1a6d2b1cd43938f2777355846e724102d4945c6d756bbed66c686a0542f7b4d15ecd8c62306fb5bb83182aa3d17cb55882967bd1c45cd861cddc852a08b31d7b317bdb3529f683610aa3e3835ad37b61586162282c40cd6d234412c0ca01581b57b0cf55f847f68900ae28fdcfd4675d414ceba1a3482bf19120f67f9dfa08307c8b4acfc1201f9c0ea9128f5f9a1bb81308f742232dde20e1aa36098a3a3a04e8f52fcf44db77044c867ba97592a276fb04d5090c13a26314b11876fe51ac9a0cb01dc527d3f865be689ecec39fe12a5b415681dd0cdbc5cf76a3e30862bc5b8a0f37a20e3234fb9b9a1f34fae080b5df3bcfc0d48d1f908a950198353bcd175a6a0c26156ddcf4e9c6736b61d65380cb449c88ea495c4a683ed0ae9cf5e17f5e10ba0ae9b2199207bdd5981057f5148f2a1aa3a44d9dd495fbca3d9ed9fdd3d358c04a0163faefe9494e63de4c16887d5f976f7bb8645f07dc18009e0270a200ea27549a0399665f2e953bac2ee51e56b2806156a1b3d1ce07c5e9c52066877d435b8b4cba04fcf898501257984ea5fdf68bb2d7839ffe9892590e0b1c8d59226cdfac86134a04210d3022b9307c96b713782589e03be36a5caea9db0be2846c160189b41a92080","0xf90211a0f60e7aa267b3e3ade5f3d3dd2a0e91a95814d31030755cb4273ab4bd8e15a0f2a0be78fbef98b939edb65c1b2376868b0478c5321c9c23e30543141d369c9ebff4a08d2e890907e3eb198e77b4327e631540478c20fd9ee689751d444d049922589ea0b298972827f64891711ab4a9439bb7c50fb64558c6d63e1f8b8e3a99a0c885dfa00a7089840e3824c666f4dd7a0bf54d37d54e98f293b197f990d9b20ab3dfcb4da04960f868e116f6d3c517429f29888edce460253797f6bef9a24a9bfcc291c64da0fa0244b2c7ffc74dc27e1a107a79678b6bfb774ed9be55757dca2b094305c6bda03a65ff2563bc18b18f9a4e601f61b51455d27383a075d233de2b83987b86d053a0178bd2bfe4d19658d4daa80f514de5a37da24efb8c8e324e68f0829caf843d01a0b22ac673820d67b66265604d2dd4e8680db453fe0a67b88aa4182f5e8acc37c0a0a1986304d192ad6c1b75e9e8d1f7e6e64e4548b4ff15121dd2cdd531678ecf44a021690283d300cc3ee391976b14c1997a5fcdb2aafad2ad00d91010ffc8c2ec47a0fd03e5ca7ac33ac851ebb472bff9008afa9d80f1c10562cb91e434b59b448e62a0bbbe2e284bc358740d893dc63815e43153e32e4f175f5f40837d034b5de7cb12a0bc914ffb505bcd7555ab63d248f85b36a670e988055e19ba667371eef8f11b5ea070dec3bbe7c27f576db8934bb06b9e87d8b1664d6b8889298007c9deb287991580","0xf90211a0bc8f49a6d128d356c08e1277b94a66b5cb33ae84cc0868a1a63f149ba8c36c33a07544c8d63d81ebdc024502c2099a2c160b35a608621c64dd3f1af9e4530c5e3da00f5e5d6e56f9dafc4a60b777041db231ef7039ec755350702abc96042f33d2f2a0bdfa09b87a9b31f795666dda6ba8bca80ac703a074290cf91e702f80d7825848a0bf9e8adfc47cfa28e8988aaaee1a6fee7e91369bc74aa82ad74e9648b6ac9fb6a0a84e67a1af29e13e3c35b5075db2e09188884241c8c8e448cddb692538b5711ba056095e7a83baccfab0dcd640b48d7a4cd546b7aebba1d328560959a5c184e6a1a037578c51c27db59387056e8b3f65b3886af297be9b386714da211e1ae31bd810a0b3a48b16c03b1c972d5bceb7cab4d6e868c4caa6331c0cae4c4ec00919de131aa086c7617e106142a979565ebdee98ab37ac4c0cb429c5db9b560f5163d76c4a89a0fb5342f266727a8bb223d89314889634f88dc101c0ee6675778c26ac5ba35b0ba08fd2327229d52ff245841d4f54aab3eb28513b5faa56cb77c9db3ba90202fa42a08301e5f5847aebe30553ca2a3221dde1acbb3292e2fd8e9e31aaa48674455eada01f196a5360fcddeea9ca2b5f6fca5c4ed55e2785b893f6f0b030cbaf1aca42cea00fe2c05ca04d437a35841c337719fad1bf1ad68bd59c248bfbeee664036df6b9a023244fbc8c3be6908883a4705393fbb957da8ba570f43a3c4943f6cc9e5622e780","0xf901d1a022670a96e5a85377453c82f9ea09b9bde9e1acda280bf120bea4d1a0e59e742aa0c49289250425469dff2c74b9bd0746208dec4ebc2906770ebbe577e4ed0ac226a059c63c4ef248ecd89bba2a55d89e68a0843df8d56a3a126eb79dc2825c74a70ca09a76945ff1fcd9db7d2041f2062a0121445b2ff909284e8e8e3a80ae95eb0f53a0e14f8eba757d958ad2f0c436add8731fa1bb10621079f6fe08e523b5d6e16536a06ce006d74c802baced58183f3c71c3b0d10a302f8fe199277b32be957812f64fa09fc4a45e6fbe15d08bbbf3cee7c9b274323afaa734519da0fc580661570e8e82a0a8b8500acf85403c783d42769bca1f3f753aceb59eb8bf89424402d2cb69e020a0a044a89d54e4327f23ba99c64d57f0e223f655f63e2265b67f38dad1f85c49c6a0cc875b0b3b6a3f330ac6959679bc271cb81c79386a6852940676d3516253d68b80a0e4ec1f19b0ab40bfe85cf186d3235de28c72ef26b14e9e8546180031e2916330a0d62267f8bda7cbf97c2cc88b9e86c7a620bb438cf48a1c2d0f0084b49f5dd6d1a0aa61ac0cad34f155f179074d0adb6e36be20be16188db0db5da933260cf15beea01c1099abecca0cd9452ea484705781263954171f8eeeab589359bd4d34f334038080","0xf8b180a0c57d35ef73d7d4e7e9254cfb19af5c1df0f81a25e37590f2a309713990dfe17e80808080a0acf132f976c1b76fe46ca08ffe31f4876623ace1da9462f28982157fce070b7a80a0df80690a6c275d2b7063b4cfe5a4dda2ceb783a87a6cc2752cf5ad5de4656c92a07ad5dc4f8327f99963ca346ca0e5483843d64920cdc9a946c8939812b2f2250580808080a0ddb167a2a63a396190e600d32c71f79dd99c4f52fd044a87678dc588ce8a8eab8080","0xf86f9e36c46041cb7b9b46ba6a06dafc260d4662483a32c905918c12ba4e4ed82cb84ef84c078802c4f9d807ef336ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","balance":"0x2c4f9d807ef336b","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x7","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":2581188,"lastValidatorChange":0,"lastNodeList":2561645,"execTime":121,"rpcTime":55,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x7","in3":{"proof":{"type":"accountProof","block":"0xf9025ba0e53b6a4a7ce1a4492b9f9607ff96f19d5354e914d615bc8a3f413d3ccaa8b869a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0f145aa50deb1dc197013d4e634e92d9683d8f662a7322065c240150d880272f7a079171295f805e13ff14be88211e3961270c0e6f15e5b32e219d0739e9e021c51a0214d31735386b5a9332709d44c1fb38954aad15964a09740c8de0726ac0d60dab901000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000200000000000000000000000800000000000000000000000000000000004000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800002000000000000000001832762c6837a120082c702845ea32538b861726f6e696e6b61697a656e00000000000000000000000000000000000000000091c2589b07bfadda0e6718eff6326b932d7d79fc057c009f3d66054134f3c4945116350f1cd3eac3ba8830b8844221ebb619d2d4143fba00da42143faefcd4bd00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x96734aac81d8ef2772c2b56a066527fed53b2a2d9713ad5043bdf6919153e175","block":2581190,"r":"0xafe8147606a8bb0bf623a898d43557fcd4c5ea17a6860c2ca3b92f4005c50ef7","s":"0x7e69ff6bc750d20cea52ca0d6fa0d0447a26d743e2a1f77cf6d4c1b91261e3e6","v":28,"msgHash":"0x8b5635af3ec6dd8db7f0314bc4c8fe438fbf2ebee6162ac79beb883b064f0107"},{"blockHash":"0x96734aac81d8ef2772c2b56a066527fed53b2a2d9713ad5043bdf6919153e175","block":2581190,"r":"0x2ba793d9b9e2dc89001c82f4dfa9e144c847cce9970a7e9b0ec1a1b0064aeecc","s":"0x0a941f31ef21f116ae81376eb9b690429fb9c79f15612d73fe2d6ec05056674a","v":28,"msgHash":"0x8b5635af3ec6dd8db7f0314bc4c8fe438fbf2ebee6162ac79beb883b064f0107"}],"accounts":{"0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308":{"accountProof":["0xf90211a03a63400d749fd0ccdbdda979f1a612c34eeb8d297626dbefe24c65a5d02cd169a0048c6ec1b685f462b0c9f80508b1c246f9bfd51d3fcc6a4a2c2cd343e11edec5a0a709646bdac1a6d2b1cd43938f2777355846e724102d4945c6d756bbed66c686a0d2dd2c3beab22d8407da580aee603d05121d941a081f2343ea46dcb5ebab5465a08b31d7b317bdb3529f683610aa3e3835ad37b61586162282c40cd6d234412c0ca01581b57b0cf55f847f68900ae28fdcfd4675d414ceba1a3482bf19120f67f9dfa08307c8b4acfc1201f9c0ea9128f5f9a1bb81308f742232dde20e1aa36098a3a3a026cf52f823a960dd89521106672e90436f85824aebc36248341f8885543189b2a0cb01dc527d3f865be689ecec39fe12a5b415681dd0cdbc5cf76a3e30862bc5b8a0dd6b731a32f7f2d70d6a36375f56bc7cf96db5a38b2978cc86cd210f7e9121baa0683796c4b745236b956ce159e78645e8083eb932cca65352668417f317256528a02cc85a68a68a98927a9bf3664396178dfd4c43ebf489f57f7c231ba40690df0ea0163faefe9494e63de4c16887d5f976f7bb8645f07dc18009e0270a200ea27549a0b34a0ecb4e7e052a8fd09dd4230afb479c3bdf6785d30b4ba3d9573a8b4b0308a0ba6e1f025568ff64c1f2491c2c944f4924bd1ee67bf6578886c213a22b04c94ea0e83974cbf2696b1963ca61727f0a78ce816e69e5364c398f4f88a8c7e404cc2f80","0xf90211a0f60e7aa267b3e3ade5f3d3dd2a0e91a95814d31030755cb4273ab4bd8e15a0f2a0be78fbef98b939edb65c1b2376868b0478c5321c9c23e30543141d369c9ebff4a08d2e890907e3eb198e77b4327e631540478c20fd9ee689751d444d049922589ea0b298972827f64891711ab4a9439bb7c50fb64558c6d63e1f8b8e3a99a0c885dfa00a7089840e3824c666f4dd7a0bf54d37d54e98f293b197f990d9b20ab3dfcb4da04960f868e116f6d3c517429f29888edce460253797f6bef9a24a9bfcc291c64da0fa0244b2c7ffc74dc27e1a107a79678b6bfb774ed9be55757dca2b094305c6bda03a65ff2563bc18b18f9a4e601f61b51455d27383a075d233de2b83987b86d053a0178bd2bfe4d19658d4daa80f514de5a37da24efb8c8e324e68f0829caf843d01a0b22ac673820d67b66265604d2dd4e8680db453fe0a67b88aa4182f5e8acc37c0a0a1986304d192ad6c1b75e9e8d1f7e6e64e4548b4ff15121dd2cdd531678ecf44a0ccc6af353cd3998dcc40f1278bca480e3bf4e0fbf296ef14b0d39c25fb0d7498a0fd03e5ca7ac33ac851ebb472bff9008afa9d80f1c10562cb91e434b59b448e62a0bbbe2e284bc358740d893dc63815e43153e32e4f175f5f40837d034b5de7cb12a0bc914ffb505bcd7555ab63d248f85b36a670e988055e19ba667371eef8f11b5ea070dec3bbe7c27f576db8934bb06b9e87d8b1664d6b8889298007c9deb287991580","0xf90211a0bc8f49a6d128d356c08e1277b94a66b5cb33ae84cc0868a1a63f149ba8c36c33a07544c8d63d81ebdc024502c2099a2c160b35a608621c64dd3f1af9e4530c5e3da00f5e5d6e56f9dafc4a60b777041db231ef7039ec755350702abc96042f33d2f2a0bdfa09b87a9b31f795666dda6ba8bca80ac703a074290cf91e702f80d7825848a0bf9e8adfc47cfa28e8988aaaee1a6fee7e91369bc74aa82ad74e9648b6ac9fb6a0a84e67a1af29e13e3c35b5075db2e09188884241c8c8e448cddb692538b5711ba056095e7a83baccfab0dcd640b48d7a4cd546b7aebba1d328560959a5c184e6a1a037578c51c27db59387056e8b3f65b3886af297be9b386714da211e1ae31bd810a0b3a48b16c03b1c972d5bceb7cab4d6e868c4caa6331c0cae4c4ec00919de131aa086c7617e106142a979565ebdee98ab37ac4c0cb429c5db9b560f5163d76c4a89a0fb5342f266727a8bb223d89314889634f88dc101c0ee6675778c26ac5ba35b0ba08fd2327229d52ff245841d4f54aab3eb28513b5faa56cb77c9db3ba90202fa42a08301e5f5847aebe30553ca2a3221dde1acbb3292e2fd8e9e31aaa48674455eada01f196a5360fcddeea9ca2b5f6fca5c4ed55e2785b893f6f0b030cbaf1aca42cea00fe2c05ca04d437a35841c337719fad1bf1ad68bd59c248bfbeee664036df6b9a023244fbc8c3be6908883a4705393fbb957da8ba570f43a3c4943f6cc9e5622e780","0xf901d1a022670a96e5a85377453c82f9ea09b9bde9e1acda280bf120bea4d1a0e59e742aa0c49289250425469dff2c74b9bd0746208dec4ebc2906770ebbe577e4ed0ac226a059c63c4ef248ecd89bba2a55d89e68a0843df8d56a3a126eb79dc2825c74a70ca09a76945ff1fcd9db7d2041f2062a0121445b2ff909284e8e8e3a80ae95eb0f53a0e14f8eba757d958ad2f0c436add8731fa1bb10621079f6fe08e523b5d6e16536a06ce006d74c802baced58183f3c71c3b0d10a302f8fe199277b32be957812f64fa09fc4a45e6fbe15d08bbbf3cee7c9b274323afaa734519da0fc580661570e8e82a0a8b8500acf85403c783d42769bca1f3f753aceb59eb8bf89424402d2cb69e020a0a044a89d54e4327f23ba99c64d57f0e223f655f63e2265b67f38dad1f85c49c6a0cc875b0b3b6a3f330ac6959679bc271cb81c79386a6852940676d3516253d68b80a0e4ec1f19b0ab40bfe85cf186d3235de28c72ef26b14e9e8546180031e2916330a0d62267f8bda7cbf97c2cc88b9e86c7a620bb438cf48a1c2d0f0084b49f5dd6d1a0aa61ac0cad34f155f179074d0adb6e36be20be16188db0db5da933260cf15beea01c1099abecca0cd9452ea484705781263954171f8eeeab589359bd4d34f334038080","0xf8b180a0c57d35ef73d7d4e7e9254cfb19af5c1df0f81a25e37590f2a309713990dfe17e80808080a0acf132f976c1b76fe46ca08ffe31f4876623ace1da9462f28982157fce070b7a80a0df80690a6c275d2b7063b4cfe5a4dda2ceb783a87a6cc2752cf5ad5de4656c92a07ad5dc4f8327f99963ca346ca0e5483843d64920cdc9a946c8939812b2f2250580808080a0ddb167a2a63a396190e600d32c71f79dd99c4f52fd044a87678dc588ce8a8eab8080","0xf86f9e36c46041cb7b9b46ba6a06dafc260d4662483a32c905918c12ba4e4ed82cb84ef84c078802c4f9d807ef336ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","balance":"0x2c4f9d807ef336b","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x7","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":2581196,"lastValidatorChange":0,"lastNodeList":2561644,"execTime":141,"rpcTime":53,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x0","in3":{"proof":{"type":"accountProof","block":"0xf90247a0edee0076485145040ca7d7c9d24cf23c1a7f9bc1fe87248c065ff360442d4e1aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479403801efb0efe2a25ede5dd3a003ae880c0292e4da0af8a65470a708a0c9b4978ef29c3994ff3ba4a7f2c1b17e06e1d938c12ac43fda0a7ddd45f904dd611b379172d2e3063550569758636b4964610506e1d889a8e37a004fd7099a88289606fe551c47d63d99232fd3d42b2ae4987f349a5e980518f39b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000010000000000000000000000000000000000000000000000000008000000000000000000000001090fffffffffffffffffffffffffffffffe840114b52a8398968082aed8845ea336d09fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cdb4b841a7b99b13945f19fdc005f125c1f2c667c1ce6b79648a6fbb2447162d1f424f20244c59defe9c14dbd459139b726688fd47995bca011a8d4a9e74e3a94e69bac000","signatures":[{"blockHash":"0x8aed31d618e2049bffe78f4b987915d7a30d1a2e08e269e1ac988430139fd890","block":18134314,"r":"0x81d88496e7ae77903427af2f5406243d29438eb1df311b4af94a6607b636f4b0","s":"0x3b2cdbb2bd2d9dc7d1b6b49f820308164597a35bebd4541d324d96d71a898136","v":27,"msgHash":"0x9e788a33be0bb7ec26ed82ff26b9d5b9c83ad7aa02c829798c872d3f4c1e7d06"},{"blockHash":"0x8aed31d618e2049bffe78f4b987915d7a30d1a2e08e269e1ac988430139fd890","block":18134314,"r":"0x55112e7bfcbc1d91d54aaf3499b8dc54c5bb66f80640885f552db78f58401f6c","s":"0x3961f3291ac71746e4a7ff207af9d67f0135a2c11c42f8065fc21551fecfd5f8","v":28,"msgHash":"0x9e788a33be0bb7ec26ed82ff26b9d5b9c83ad7aa02c829798c872d3f4c1e7d06"}],"accounts":{"0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308":{"accountProof":["0xf90211a069aa361067cc9a94f196984724e76d5e1c6b5e8373e3e05f53c26ba7c0c563e0a0b7ac788ee9660983aa3ab97de29bc8f5f4fb6c360e6088b8d52256e2a12299baa0d8273598b0cef4fdcd502ceea30eaaf63bd42a4d0396eca55a8d140f9575b175a0d6857564e7ee2a7c290dff8f76a9fd9c1135a06a0563055e9bbb4441057aa2aaa0bb5f20c9b55bee5ba635e4ce073a54c5295252ce8d1e6a31701e4cc54d601f00a0fd09e0d9c4271e9a368786f846dd7a5d90061d4496359efac0c9d62430810d02a0d8a42bab9eef0681afb23c4d0f24a51a3bd48262ff270fb71852581989892658a084a31eb2ec6ee94d2495ce951f589fc619c1c3c900029d77a6574404c8074b62a02b8ddf04973d890b2980c3e1bd3fca1d49c595ba520029035bd0fea7baed3be6a06507a48d933dadb09f5a3fa943ab692b079526a71fd8689027ed86ca8eacce7fa00c2d867ac7bc7fe84b98505ec622af35b04721596ed291b042e8b4a47be8099ea01a01ee64a658b6da05a979768a5139b5980d5d32c7b23be4013f1829a5e9473ba04d3c3c43544b19df585056a2d64bbbf21572946e6ae58fd8de91c19e7891ddf6a041fd7c4d718284b9334724d91b17dc7c8b63e17fc409f8537d44fc59afd7a776a0dccdc7f7debbb2ae1ec8a15af3b482cd0a3a42eb9429fefdb9cd1823f89df7e2a09800a307676679531f8d19b992deb3d19d4fc24f3b1ea611788c336ae700854e80","0xf90211a07eb07ee398a06ecdadb9abf07e338928a3e3ace1fcdfee6249eba5df461a1b80a098e3cd5b293a680ab244cb7558f237f7a6b1a5a67b04b4fc922de84af1c0778ca04f89c88398ba5eec93ca4c87fda37593ed758a2f38642050db64445200aa1449a0dd94fd561f433668705462091a500f1c3e5e49af55bdb74cb608f6e39f77fdb0a018690234925bbf944065bcb9f0b40d9432d6ba62b48267225fb2c6fd0ee0cb4aa0b44c414811cec2bd3b6427314b5c427cf39c50b9dca811a15af4e87adb8a7bcca00210b721c4bd5a3fc8cd5c667fcda44f1df6e3baf0fd502fa05429284fc7d09ca01185330eeff42c0e69b345fb1fc8222c9a02ddad20c59a9a5730a8efc418ed2ba0a69438d8754ec7baeebf6e7a24f782771c1ea4c4ac22a464eb416e8cf16bd374a07b3c21ca9646a46d0700fe8f534800de27645fdde696c7597ffbb9fbf3f630a3a0f64741d82ee1789512998a305c62d80c6b13f57cb1fe44b4dcd144c43d54d183a05105652532da0bf4300a40d2289f46eb8eb64707403d73c7dfc71387808c16b5a01043d4c321d488ed999dfb5c1278fbfa63ef6b571eed2058e1d8ba55a8916e8aa0c7039834ade2dd9ebcd96e96efe9d65a8c52bc182264e751f6c85f035fa5aa94a06c79e0cdc8411b15d8b48cea00dd2469e3e52f89ea69141af18590eb9b9923b3a0809f994d0bc6f9fdec835ec766bd89dc0a61b347e3e3fdc486a34556b1c0e26b80","0xf90211a0d8e688a8e11394292bc0373a87a91fbb8e72be38c2b94a86034b512b658fe7dca013ca4e796bdd3d0f0121274def902a985992dbdcbbc7a3f6a295c06e95f5a43ca08cdfc84a295b09df36df15e8be9ad1a709cc3e0f0f010a5f788c0caeb6a25150a0c5b534abe7d6d5fd4bcf0fedee8b32e595ef4e5ba141c71e39b631db1c58d509a0a76b4dafa34e830166f3dac433799ea752de95ca3407a95dba3ee86363c2afaba0d593225f7e618b927cfc05f81904902c7268a16616f57e757df29c6d46d17492a036f4a6746a0e284780b84978b5d7a328451546a0141b84ad395fca95b5a9ba2ea0b830e577b1ecb8c6ae3d30788b7cdda1a55626f808490ee5f082ec8108d8fbf8a0753f2ae942f1e30ecc0673b3b3cd4b4461ead781082c22aac0c7e6d065701cdaa042087120532f6470a5e75f779c280421b1f8af5839a971fadf77265f5f8384c4a0e64b470b3ceba8d7188eb27e3c5739f54f7c01ac7c47fd9e7a2fb4945b62f7c3a0050fd36ba73706d6e3c90ba4ac0b90e169928a69db8cf86ae6c7e2ac7b9719fba00b3a80cf70aa7932e6ab852bfbbcd4b9feff0038bce12438f56b20d1dc669f92a0b33944e1b3f19ba09a5c3440180d75a0a5094141f196858ffaa50ec8b3290923a05c21e67421a4d7aa460c0b8add86db957b37e87e77aed65fba7c4c05cb60d3c6a0d16374d9f1f90cef6d344f59a675f87b7e760c714192693cd12acf4d77086fd380","0xf90211a0ab241fcdb1f5763b438f05778ad25c582838511a87064b37af6394f6455175aea04ad7a6136985a4d0dba9363c6ebaa3916c10c3e28b86d33a22d27e0119b8a277a00dc1057d548bca30e1c8d483d235e833baf7db6c430a456f3671d0274a24dd7aa0e6b4029934f3d98c1b2f271bfcec3732346999f56a1227c211992b7891c9dbc2a01774f41c36867f58099054f92ba97d5f99657fda4f699a4b53b775c5fd77fdf4a0fd0c11b69d13734999069703e0d4e8f8d2d41015fc60248d63e48024a82db244a04bf184beb7b3498f953203b8f40420120e9d9315eb658f6180bc2289b9e814d7a064a6aa2ced80a00cb81269e3d993ce97338a704c2e6a1d8136cfecac022b5765a0bfcb35a2c5c3ea9a83b65c44c7ff6084a1583d3d7b1ef107f71a35d8e8b9a686a0866c555f6878cc705dd4a2ef80007c586e96f017aaa551e7e29bc9973c8efa57a07c5fb28179bfe2048059ef2c99a3c99f3526e3b7729e9c48d12e5b04e4300a0ba04edd1d25fd3e1056994698082c2b475f3728e2c04d4d89dc4a50e3de6f00621fa0f2a6e35577f4f230e654da1776a5c8cfab74027b18cf63ab2b3bb56bd31741a5a03ca64749dccad0bc3c59d6b790b1f813f46e179b29ec082bdf894f5afdc1a56aa06b4a82bb26556204b58c6a1bb01284d5834b714838b5aac7363a31283a582b03a07fbf64c0027dd516815b4870b2050e7b204ce97bdd7f3cf2290e3f534394115f80","0xf901f1a00e4083add88ee2316186cddde82407b2440e4f9c893588057dd7b0d6e40a4c66a0f6dc7d959f6f2cbd078c68065c82298945b92913421ecf4c71077ed85d2a834da04c298c419ef59dc58cd33bc5787d688ae998d9faa46cc5a4b5485c90de039838a0197e052a15a37dc331a090f0b9b3c65bdb8d205a35b24e90bf09c7e48b33db53a03593c4e459b3be6f5c597df23eed97361b398700b782369c8f1871393a587feaa0e36425c056214c133751b24d189e104c8827c2c997e89792e76ca32f3b1d01b6a0bdb6c265f1610196ef605a1a663f26970e7af0617e409ffb868384b2715c3d3ca01eadc0f4cf431610ba100b7036f5ab47bb507d8ed94f7c613685648e04871bc6a0d44d8f9a921462945ce9cb0a2e3f407a592458514497fa0612ed04125d4374d9a0a44791759cde2999a147ce120418c23f7dd907ce462ee6172c28e9a5e1dd2fe9a0be1b5729e3c02e3cf94e04bf80f5d62c0321f79e80fb362ef9d5b9375b6f5e72a00bc3227cae16a0cd75f3506ae1eef76336a18523f02bc550d4d7700eb47f74b6a09b6d0f504138f56a887857eeb8040a341a000fec42b43a9d41b2d284e62695dd80a024f7f7ba92717a6ca602dbbb958e89a0cd54d69be0372f39c5b672d3caf4e9c4a0efbe68f1b03d030f2456670c97e65f266d576394fa72e85f18df328dd255c44e80","0xf851808080808080a0624a98abc7a5278a048b38a458e2d872fe7eee186800fc255f6b7109e03f38f980808080808080a0a92b6f3bf8e3eab8554493f07705e63c59183fc636a0118ba555e2a1bc9265b58080","0xf86f9e20c46041cb7b9b46ba6a06dafc260d4662483a32c905918c12ba4e4ed82cb84ef84c808829a2241af62c0000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","balance":"0x29a2241af62c0000","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":18134320,"lastValidatorChange":0,"lastNodeList":18098311,"execTime":434,"rpcTime":139,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x0","in3":{"proof":{"type":"accountProof","block":"0xf90248a04a9bd3b371ad9193260375e72c7e1c59483bc24aabc40fae6865f9d23965417da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479403801efb0efe2a25ede5dd3a003ae880c0292e4da03ddcfcf0aea1e75f9ef027d1b9180589aa03172e79df673c2b0c44e4b2155a37a0fd7f0993b063dc9a6f07916a2aa4b350e69142e2b509678be1f9d7244f96c3c5a0d5a9474cedcd4c4f739c4f10cc0104b92f822d0e880fc897149f2c27cd6a9e46b901000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000010000000800000000000000000000000000000000000000000000000000000000000010000008002000000000000080001000001000000000000000000000000000020000200000008040000000000000001000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000002000000000000000000000000000000010000000000000000000000000000000000040000000000010008000000000000000000000001090fffffffffffffffffffffffffffffffe840114b534839896808301bda3845ea336f89fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cdbeb84101a8ae118987c55d4c8d5f3a12759ff1b460579bcac6cdf0fdf12da609110286422c1346c73e41a94eb053885b23729eb307a2dd02b9b74e0368665c2c6f473c00","signatures":[{"blockHash":"0x2fc51b196859b60028566ee03ff2c4cc0622dfdff99f756002f7f27bc537b066","block":18134324,"r":"0xc976c0cdbf6605e1ec153942ddc91b827fc9d410da8a6841a14c394645818908","s":"0x405910d80ee6aefc28ebccf953b9e881654bc2d059c54e1c2f8fff9dbc38367d","v":27,"msgHash":"0xfe57bb8b31cb8bbb7fac80529555c67dff63ccc69ac07fa269ad04075f6ff3f9"},{"blockHash":"0x2fc51b196859b60028566ee03ff2c4cc0622dfdff99f756002f7f27bc537b066","block":18134324,"r":"0xd9776be5a0bd34195ab5009e0ac5af71baa3b08e81ba81dfc8fcb70b86db5b61","s":"0x09b9fa1d3b75fef92cd690cbd213a896e7274e16d8a12850f3dc30488e269e46","v":28,"msgHash":"0xfe57bb8b31cb8bbb7fac80529555c67dff63ccc69ac07fa269ad04075f6ff3f9"}],"accounts":{"0x0b56Ae81586D2728Ceaf7C00A6020C5D63f02308":{"accountProof":["0xf90211a069aa361067cc9a94f196984724e76d5e1c6b5e8373e3e05f53c26ba7c0c563e0a0b7ac788ee9660983aa3ab97de29bc8f5f4fb6c360e6088b8d52256e2a12299baa0d8273598b0cef4fdcd502ceea30eaaf63bd42a4d0396eca55a8d140f9575b175a0d6857564e7ee2a7c290dff8f76a9fd9c1135a06a0563055e9bbb4441057aa2aaa02e04f2d5cbdd46a86b1074ab8aa11766fb9929b691f715ec42affff2797209b8a0b1f8b3aaec264087a88fee56b2b88ceece1aa2ba23d0392a5fac8e1fb4d47dfca09c48433502293ced310f63e159e67df47fef6ccab0867e83fe682995faeef80fa084a31eb2ec6ee94d2495ce951f589fc619c1c3c900029d77a6574404c8074b62a01453223a675ed02ce1c6c4ac69edd158cfcd67bcc21c91c5af245552dfc016bda06507a48d933dadb09f5a3fa943ab692b079526a71fd8689027ed86ca8eacce7fa0d92e8e67315debf3e1f1d6984921565009995c77ed65dc00cd2430ea0cf248baa0bce1273d91fca7983989b932815051edf80574561a7d5cbd56a93fd2c3ca9806a0e025c3c10f257ca9afcd17f2c80ab97b616eafc3280796035eda2ff4b4fa7024a055c531f1725c9da0c9413ec691de4d6c369a40c4b0bf36cfa03d66cc1f20fbb4a0457962c0b4ecc1d91a28ce35b164b64b3b6c7d396a11d758d45088361eb33b6fa0d8ceda5e0296e0257beb47732c0e7af7b2dc5214dc2dddcb3ab2d7483c3e760d80","0xf90211a07eb07ee398a06ecdadb9abf07e338928a3e3ace1fcdfee6249eba5df461a1b80a098e3cd5b293a680ab244cb7558f237f7a6b1a5a67b04b4fc922de84af1c0778ca04f89c88398ba5eec93ca4c87fda37593ed758a2f38642050db64445200aa1449a0dd94fd561f433668705462091a500f1c3e5e49af55bdb74cb608f6e39f77fdb0a018690234925bbf944065bcb9f0b40d9432d6ba62b48267225fb2c6fd0ee0cb4aa0b44c414811cec2bd3b6427314b5c427cf39c50b9dca811a15af4e87adb8a7bcca00210b721c4bd5a3fc8cd5c667fcda44f1df6e3baf0fd502fa05429284fc7d09ca01185330eeff42c0e69b345fb1fc8222c9a02ddad20c59a9a5730a8efc418ed2ba0a69438d8754ec7baeebf6e7a24f782771c1ea4c4ac22a464eb416e8cf16bd374a07b3c21ca9646a46d0700fe8f534800de27645fdde696c7597ffbb9fbf3f630a3a0f64741d82ee1789512998a305c62d80c6b13f57cb1fe44b4dcd144c43d54d183a05105652532da0bf4300a40d2289f46eb8eb64707403d73c7dfc71387808c16b5a01043d4c321d488ed999dfb5c1278fbfa63ef6b571eed2058e1d8ba55a8916e8aa0c7039834ade2dd9ebcd96e96efe9d65a8c52bc182264e751f6c85f035fa5aa94a06c79e0cdc8411b15d8b48cea00dd2469e3e52f89ea69141af18590eb9b9923b3a0809f994d0bc6f9fdec835ec766bd89dc0a61b347e3e3fdc486a34556b1c0e26b80","0xf90211a0d8e688a8e11394292bc0373a87a91fbb8e72be38c2b94a86034b512b658fe7dca013ca4e796bdd3d0f0121274def902a985992dbdcbbc7a3f6a295c06e95f5a43ca08cdfc84a295b09df36df15e8be9ad1a709cc3e0f0f010a5f788c0caeb6a25150a0c5b534abe7d6d5fd4bcf0fedee8b32e595ef4e5ba141c71e39b631db1c58d509a0a76b4dafa34e830166f3dac433799ea752de95ca3407a95dba3ee86363c2afaba0d593225f7e618b927cfc05f81904902c7268a16616f57e757df29c6d46d17492a036f4a6746a0e284780b84978b5d7a328451546a0141b84ad395fca95b5a9ba2ea0b830e577b1ecb8c6ae3d30788b7cdda1a55626f808490ee5f082ec8108d8fbf8a0753f2ae942f1e30ecc0673b3b3cd4b4461ead781082c22aac0c7e6d065701cdaa042087120532f6470a5e75f779c280421b1f8af5839a971fadf77265f5f8384c4a0e64b470b3ceba8d7188eb27e3c5739f54f7c01ac7c47fd9e7a2fb4945b62f7c3a0050fd36ba73706d6e3c90ba4ac0b90e169928a69db8cf86ae6c7e2ac7b9719fba00b3a80cf70aa7932e6ab852bfbbcd4b9feff0038bce12438f56b20d1dc669f92a0b33944e1b3f19ba09a5c3440180d75a0a5094141f196858ffaa50ec8b3290923a05c21e67421a4d7aa460c0b8add86db957b37e87e77aed65fba7c4c05cb60d3c6a0d16374d9f1f90cef6d344f59a675f87b7e760c714192693cd12acf4d77086fd380","0xf90211a0ab241fcdb1f5763b438f05778ad25c582838511a87064b37af6394f6455175aea04ad7a6136985a4d0dba9363c6ebaa3916c10c3e28b86d33a22d27e0119b8a277a00dc1057d548bca30e1c8d483d235e833baf7db6c430a456f3671d0274a24dd7aa0e6b4029934f3d98c1b2f271bfcec3732346999f56a1227c211992b7891c9dbc2a01774f41c36867f58099054f92ba97d5f99657fda4f699a4b53b775c5fd77fdf4a0fd0c11b69d13734999069703e0d4e8f8d2d41015fc60248d63e48024a82db244a04bf184beb7b3498f953203b8f40420120e9d9315eb658f6180bc2289b9e814d7a064a6aa2ced80a00cb81269e3d993ce97338a704c2e6a1d8136cfecac022b5765a0bfcb35a2c5c3ea9a83b65c44c7ff6084a1583d3d7b1ef107f71a35d8e8b9a686a0866c555f6878cc705dd4a2ef80007c586e96f017aaa551e7e29bc9973c8efa57a07c5fb28179bfe2048059ef2c99a3c99f3526e3b7729e9c48d12e5b04e4300a0ba04edd1d25fd3e1056994698082c2b475f3728e2c04d4d89dc4a50e3de6f00621fa0f2a6e35577f4f230e654da1776a5c8cfab74027b18cf63ab2b3bb56bd31741a5a03ca64749dccad0bc3c59d6b790b1f813f46e179b29ec082bdf894f5afdc1a56aa06b4a82bb26556204b58c6a1bb01284d5834b714838b5aac7363a31283a582b03a07fbf64c0027dd516815b4870b2050e7b204ce97bdd7f3cf2290e3f534394115f80","0xf901f1a00e4083add88ee2316186cddde82407b2440e4f9c893588057dd7b0d6e40a4c66a0f6dc7d959f6f2cbd078c68065c82298945b92913421ecf4c71077ed85d2a834da04c298c419ef59dc58cd33bc5787d688ae998d9faa46cc5a4b5485c90de039838a0197e052a15a37dc331a090f0b9b3c65bdb8d205a35b24e90bf09c7e48b33db53a03593c4e459b3be6f5c597df23eed97361b398700b782369c8f1871393a587feaa0e36425c056214c133751b24d189e104c8827c2c997e89792e76ca32f3b1d01b6a0bdb6c265f1610196ef605a1a663f26970e7af0617e409ffb868384b2715c3d3ca01eadc0f4cf431610ba100b7036f5ab47bb507d8ed94f7c613685648e04871bc6a0d44d8f9a921462945ce9cb0a2e3f407a592458514497fa0612ed04125d4374d9a0a44791759cde2999a147ce120418c23f7dd907ce462ee6172c28e9a5e1dd2fe9a0be1b5729e3c02e3cf94e04bf80f5d62c0321f79e80fb362ef9d5b9375b6f5e72a00bc3227cae16a0cd75f3506ae1eef76336a18523f02bc550d4d7700eb47f74b6a09b6d0f504138f56a887857eeb8040a341a000fec42b43a9d41b2d284e62695dd80a024f7f7ba92717a6ca602dbbb958e89a0cd54d69be0372f39c5b672d3caf4e9c4a0efbe68f1b03d030f2456670c97e65f266d576394fa72e85f18df328dd255c44e80","0xf851808080808080a0624a98abc7a5278a048b38a458e2d872fe7eee186800fc255f6b7109e03f38f980808080808080a0a92b6f3bf8e3eab8554493f07705e63c59183fc636a0118ba555e2a1bc9265b58080","0xf86f9e20c46041cb7b9b46ba6a06dafc260d4662483a32c905918c12ba4e4ed82cb84ef84c808829a2241af62c0000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"],"address":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","balance":"0x29a2241af62c0000","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]}}},"version":"2.1.0","currentBlock":18134330,"lastValidatorChange":0,"lastNodeList":18060209,"execTime":887,"rpcTime":691,"rpcCount":1}}]',
+ },
+ "eth_gasPrice": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":"0x2540be400","in3":{"lastValidatorChange":0,"lastNodeList":9941433,"execTime":59,"rpcTime":59,"rpcCount":1,"currentBlock":9941952,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":"0x1a13b8600","in3":{"lastValidatorChange":0,"lastNodeList":9941433,"execTime":61,"rpcTime":61,"rpcCount":1,"currentBlock":9941954,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x49504f80","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561645,"execTime":37,"rpcTime":37,"rpcCount":1,"currentBlock":2581199,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":"0x49504f80","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561644,"execTime":51,"rpcTime":51,"rpcCount":1,"currentBlock":2581206,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":"0x3b9aca00","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18098311,"execTime":80,"rpcTime":80,"rpcCount":1,"currentBlock":18134340,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":"0x218711a00","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18060209,"execTime":251,"rpcTime":250,"rpcCount":1,"currentBlock":18134355,"version":"2.1.0"}}]',
+ },
+ "eth_sendRawTransaction": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":"0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc","in3":{"lastValidatorChange":0,"lastNodeList":9941433,"execTime":69,"rpcTime":69,"rpcCount":1,"currentBlock":9941954,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"error":{"code":-32010,"message":"Transaction with the same hash was already imported."},"in3":{"lastValidatorChange":0,"lastNodeList":9941433,"execTime":393,"rpcTime":391,"rpcCount":1,"currentBlock":9941959,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561645,"execTime":485,"rpcTime":484,"rpcCount":1,"currentBlock":2581210,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","error":{"code":-32010,"message":"Transaction with the same hash was already imported."},"id":1,"in3":{"lastValidatorChange":0,"lastNodeList":2561644,"execTime":77,"rpcTime":77,"rpcCount":1,"currentBlock":2581214,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":"0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4","id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18098311,"execTime":519,"rpcTime":518,"rpcCount":1,"currentBlock":18134361,"version":"2.1.0"}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","error":{"code":-32010,"message":"Transaction with the same hash was already imported."},"id":1,"in3":{"lastValidatorChange":0,"lastNodeList":18060209,"execTime":80,"rpcTime":78,"rpcCount":1,"currentBlock":18134378,"version":"2.1.0"}}]',
+ },
+ "eth_getTransactionReceipt": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","blockNumber":"0x97b3c3","contractAddress":null,"cumulativeGasUsed":"0x8ac24e","from":"0x6fa33809667a99a805b610c49ee2042863b1bb83","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","transactionHash":"0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc","transactionIndex":"0xb0"},"in3":{"proof":{"type":"receiptProof","block":"0xf90215a046e5562fdb181c97b249a9a7c7c9f3ed5fefa79933076145d9e7eeb918c1fbaba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca09622dd3c5aeac08501befd47dfeb85a97c387d14b2c1b681df71d895ff3b561da0b71ebe65ee0f94ad03470bdf17c6db243bb13c0e31b93e079f06167a0567a5fba068d6ab77efa228f3502951c7d10ef0df55c178225403b94dbff338a03cd57df1b9010030622ea000c360cc0811520062001a4880842f4724a180946005881a00081523040691c21b00348e86343252e216912050a0c0600118147790cae476332c7120344501048b50c612c8a0c5ad20837c0e6246b11ed24d3000ae0a49804286a91078a4a1228212d29189274690000616002c6932381c285cc12a281c1cb2337b180a58800048047458000492204e21327c79818d3cc7a88392c0424220e0bfc410869e60b2196ca100ee020eba2255b091b8953418806400c0cc3353e51a0c14c10718250e8b0401025ca9d040c51002552a164918834b849400c0801f175152108030dc8294321459117240d6411861846c002420c4600e90c06c32c648d16e7d8707f4d7ad891a828397b3c38397eacc8397d483845ea43d3694737061726b706f6f6c2d6574682d636e2d687a34a04813ae0b44ee15395b2aa6de24eac1815972089c53eb95cb761c381c16d8c17788d3e6cba4059c6723","txProof":["0xf90131a0719764e4d985879bc4119bbdda3af1d443e64247f09deff59567fb7911745ca2a0d3c8877fdf7ff17527098d89971d6495a1460b9af263a312a06a4ab19ad581f7a0d75aeed57b86dddee818cf84a7ac981643f20e1f7ff1904d7517b2b59f85473fa085db5c66945be0c839af236c164ed482dad3bab885376ea9f4574d10d426996ca0feb154525e55d68979457b1323b36976005cb442952d0eba03d7abb443156162a0f7e85ffdc96c24dac80ce1ffe0ae085e64de92c218a176136d58c23195801645a0120a203bd0bd1f8b1ddfd171b6cf002280214157a986aa999af132ec059d31bba06081a6ab711eb369bf2ec07bad20984d82bc71d126847761b19bedc568a8ec0fa0ffa32dbc1157ec798d20750506f4d775935a1af61952353cc6f82cc3254a798a8080808080808080","0xf851a0fe7fdfbdeab78a4a94626f1f66bc600edab0b6dfa5e6b6bfb87b602e531410e4a0875b5a4fd94c3509beb7e0d41c214a2ecaf8e3142f1fe38766b5b263b2181d56808080808080808080808080808080","0xf8918080808080808080a0166dc06183f59dc2e09ac7f2258948b26449ea0b002999d0e47cc83f9639a589a0ee3eeec00f8eb18aa36243a01edf217309b821a7a1a778f21f400ae988793722a00a553d91d77c9ae3f8a2d3547b2b47b4982bc8948dc1abd876c7462c896d2425a01a560155edfa372bcfa89e54782e2a67838d14c186d405993cf4e27bf7aa641f8080808080","0xf90211a0612a5b5f12c69a115293849592d1c5c3d67c1ed9bc151e601657855daafc9e09a04fd886bc9044696aff025c142652da870bb9c9b12a05065e43a835081a6059dfa0e26daec2c144d55dca2eebd4e49ce8fee15fe9c838c8251df628786df219fc48a0efe0c03f6fa0137b2d428c3c98fdeb79470f172a5a314474e27f4297f2ae72d1a0cfe27fd1c6632705932d012ff2e1d60a66e7df86cdf06b770e06170c05cfe272a09e2947217ee06d376aa2b955ab3f8d18de9d17002a4ae618acf153b84c39629ba00f5bea17bd74291acddeb1e065315f698d5e9446daa2b9b1dbe891a8e6f2046ea0a084d3e7ee8fdf999fc990905fa3a946bdadffcfc6558232b61148547d80525fa05ba7f9bec0f2fc47f391020841a39895ab2688ff9e503c0a769d3c071a1175f4a04f6745824c2b4f697a08c122ea28452b05731e820d814c5121b13e789a73392ea06b80aa7c572248a0c7fd72a3bd84e0c77978cdba01e0b356c3ce0b7e687d30b7a0579fd7e89a2d78468a3f164cd0dfb2b76c6c1fc7800778e53271c39ce446baeba0844161e117e57b6fd55422f01f4c90eefb15b5eedc90493ea6c9e0a2157bffa1a0792c69f21d5e6df97cc10854dc5fb3b1029a26bb8efeadda7f48b9d7debdf39fa031fbe76131482e438be25313efdb1996c0777b38221d4b27cc3f07802ad0f430a0bc7e2eb7f6ab00f835045400c1675764332de22f49f477dbeb6386d783cb3a6180","0xf86d20b86af868098502540be400825208940b56ae81586d2728ceaf7c00a6020c5d63f02308845741bf838026a070af62c714808c7607ebe2cc756f20bed9790e5f5f20b192a83f689157a44bd0a0768a5d94766f1645e652dbef3826eed94074b5481a453ad12aa52ae6f8e42606"],"merkleProof":["0xf90131a06d62f4a7b42cf6729452fcae08b05731dfee28dae458f816c89e57ffeaa5c147a0e43fcb9750c4ca6b2edcceeca9f1f229422fd93bb18234648a9f17055eb2a8f9a04d140e4ef403bcb15429030bccad92459ac4178b8c929460473de9c412441089a03d46fc7ba9de3aa7823269232f06006d8a081dd6e454cf2e074a724b4024bffda0e2f94d34dc2af166d9dc5d633bbd7772b543cab746659352a3e3ea17dcecbbdca0d8263dd7869059f52e93ed14653a18edb2aae2403c4568c0db39419e030a1690a0cff0d0acd407ad79e570b7620f0dcc18adab15f0285080b6875d47f5acb3f937a01ffeb4235e305712d4c5b0ab0facca8f98f76da6044a4489e66070ea87184cd5a09764cf79d39a4ea9644e131b59c23b717c785aa9d6b967b17ba26d27625ac7fe8080808080808080","0xf851a0b022033d0b8c80ca6292d85be0981d41eee8df9b08e8b9a6b290d5efccbd460ba01cd0232ea3c15beaa979152d7138ce8773ebbe418783a70fdd83f90d798583b4808080808080808080808080808080","0xf8918080808080808080a0830827c187af66cbc39d20f93093d6527a0a25c4a4b2bf82fb231e3a04aec0c3a0e1e87b554ff61a9fc87e1546715934889e33cc3067a9660d2a94a52643c7540ca08ce688be748752375d8c8e5b635a19112ae7268041879ed0818e7d46b9c1f713a0890b5bf9539a40e77ecabf406f2d33cc94022ae7d3483c82a0d52b2e1c67dd718080808080","0xf90211a05902e6d28e316fa3355c75712cff36833028fc09f74d1d191fe05e2f3af16272a04bf7d9097d42c812b885d75f4c287b29960c636cd0b4a323c06e74b1c6ad98a1a088c0cdd525ae542fc92fcfeaa0f8a420948b2493415c2dca10eae22b0c3c1313a0031c44e08c34d5179602dfd3d63afcb504e2f35d10966659f39b5634b2e65a96a06618dd068c6f3c2dd8c62111d275134817c2d1bd46132cc6bfcb1493c8c84fd9a0352a72e7eaa5d3d5162b540d8ff3c4e172b9dc1b72361afe2e76d4fb86c57feda0c8f973f01bf2f87504347bef1c0fe6912e10fed3216b4b942e936cfe14da5026a057cad5c2eb30e9688abd2bdd47eccfa835c27dc2b9d1f99b51148f2958ce48ffa0913373a8b8dba5586d50c6e19549a7f9490618c8833c52cd42331b082aa9cefca0af6aeae947a0779326470e136fa0f71f751578f184bea1e84226dd5ac4144a48a0471cb27330f43b2d5ae797c439f99262b3666bcd5ce49a56a82ef2c8a7343bd9a094d690a5853840cedc2c166526cfb41d5f6d971c829e8c8a10287d258e6634b8a0218b082fdb8ff0ff66b897a8deab7817f08af0fc7ca16f8b6bfdb85bad95771ea0028a51575ce91b801195fd61eee8eb71f6d171b0dceb55046c1ac5a0e715e063a0175092f490ad4efe476654291ea39d45bfb8e646d7815f6fe4caffb9cab1727ea0b1c5995b3c27e97bf980c510b48ae499389c1ba606bf7a69d80e3d6e6d23870c80","0xf9011020b9010cf9010901838ac24eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":176,"signatures":[{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","block":9941955,"r":"0x367f8a584bfb2e9e78c4509ec9b25a91b626af4656412b421332aea07108be8a","s":"0x41803c879d96ff96c1dfd86f735d4a1c0dd2d0f148a8750ca817dcba07972262","v":27,"msgHash":"0xd41fdbf5c8e728149498aa95c0c962c7b1b208111376f9a2b27287febc15c9c0"},{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","block":9941955,"r":"0x9fab286a0d0011bfefa8828889e92868e28305ab411a247b54140052d835b0a1","s":"0x0bac8dc43fca7970db185f1823e5633401cae913a540fc9e4e6572b767925514","v":27,"msgHash":"0xd41fdbf5c8e728149498aa95c0c962c7b1b208111376f9a2b27287febc15c9c0"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":9942900,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":7086,"rpcTime":6733,"rpcCount":3}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","blockNumber":"0x97b3c3","contractAddress":null,"cumulativeGasUsed":"0x8ac24e","from":"0x6fa33809667a99a805b610c49ee2042863b1bb83","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","transactionHash":"0xb13b9d38642216af2545f1b9f882413bcdef13bec21def57c699d3a967d763bc","transactionIndex":"0xb0"},"in3":{"proof":{"type":"receiptProof","block":"0xf90215a046e5562fdb181c97b249a9a7c7c9f3ed5fefa79933076145d9e7eeb918c1fbaba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca09622dd3c5aeac08501befd47dfeb85a97c387d14b2c1b681df71d895ff3b561da0b71ebe65ee0f94ad03470bdf17c6db243bb13c0e31b93e079f06167a0567a5fba068d6ab77efa228f3502951c7d10ef0df55c178225403b94dbff338a03cd57df1b9010030622ea000c360cc0811520062001a4880842f4724a180946005881a00081523040691c21b00348e86343252e216912050a0c0600118147790cae476332c7120344501048b50c612c8a0c5ad20837c0e6246b11ed24d3000ae0a49804286a91078a4a1228212d29189274690000616002c6932381c285cc12a281c1cb2337b180a58800048047458000492204e21327c79818d3cc7a88392c0424220e0bfc410869e60b2196ca100ee020eba2255b091b8953418806400c0cc3353e51a0c14c10718250e8b0401025ca9d040c51002552a164918834b849400c0801f175152108030dc8294321459117240d6411861846c002420c4600e90c06c32c648d16e7d8707f4d7ad891a828397b3c38397eacc8397d483845ea43d3694737061726b706f6f6c2d6574682d636e2d687a34a04813ae0b44ee15395b2aa6de24eac1815972089c53eb95cb761c381c16d8c17788d3e6cba4059c6723","txProof":["0xf90131a0719764e4d985879bc4119bbdda3af1d443e64247f09deff59567fb7911745ca2a0d3c8877fdf7ff17527098d89971d6495a1460b9af263a312a06a4ab19ad581f7a0d75aeed57b86dddee818cf84a7ac981643f20e1f7ff1904d7517b2b59f85473fa085db5c66945be0c839af236c164ed482dad3bab885376ea9f4574d10d426996ca0feb154525e55d68979457b1323b36976005cb442952d0eba03d7abb443156162a0f7e85ffdc96c24dac80ce1ffe0ae085e64de92c218a176136d58c23195801645a0120a203bd0bd1f8b1ddfd171b6cf002280214157a986aa999af132ec059d31bba06081a6ab711eb369bf2ec07bad20984d82bc71d126847761b19bedc568a8ec0fa0ffa32dbc1157ec798d20750506f4d775935a1af61952353cc6f82cc3254a798a8080808080808080","0xf851a0fe7fdfbdeab78a4a94626f1f66bc600edab0b6dfa5e6b6bfb87b602e531410e4a0875b5a4fd94c3509beb7e0d41c214a2ecaf8e3142f1fe38766b5b263b2181d56808080808080808080808080808080","0xf8918080808080808080a0166dc06183f59dc2e09ac7f2258948b26449ea0b002999d0e47cc83f9639a589a0ee3eeec00f8eb18aa36243a01edf217309b821a7a1a778f21f400ae988793722a00a553d91d77c9ae3f8a2d3547b2b47b4982bc8948dc1abd876c7462c896d2425a01a560155edfa372bcfa89e54782e2a67838d14c186d405993cf4e27bf7aa641f8080808080","0xf90211a0612a5b5f12c69a115293849592d1c5c3d67c1ed9bc151e601657855daafc9e09a04fd886bc9044696aff025c142652da870bb9c9b12a05065e43a835081a6059dfa0e26daec2c144d55dca2eebd4e49ce8fee15fe9c838c8251df628786df219fc48a0efe0c03f6fa0137b2d428c3c98fdeb79470f172a5a314474e27f4297f2ae72d1a0cfe27fd1c6632705932d012ff2e1d60a66e7df86cdf06b770e06170c05cfe272a09e2947217ee06d376aa2b955ab3f8d18de9d17002a4ae618acf153b84c39629ba00f5bea17bd74291acddeb1e065315f698d5e9446daa2b9b1dbe891a8e6f2046ea0a084d3e7ee8fdf999fc990905fa3a946bdadffcfc6558232b61148547d80525fa05ba7f9bec0f2fc47f391020841a39895ab2688ff9e503c0a769d3c071a1175f4a04f6745824c2b4f697a08c122ea28452b05731e820d814c5121b13e789a73392ea06b80aa7c572248a0c7fd72a3bd84e0c77978cdba01e0b356c3ce0b7e687d30b7a0579fd7e89a2d78468a3f164cd0dfb2b76c6c1fc7800778e53271c39ce446baeba0844161e117e57b6fd55422f01f4c90eefb15b5eedc90493ea6c9e0a2157bffa1a0792c69f21d5e6df97cc10854dc5fb3b1029a26bb8efeadda7f48b9d7debdf39fa031fbe76131482e438be25313efdb1996c0777b38221d4b27cc3f07802ad0f430a0bc7e2eb7f6ab00f835045400c1675764332de22f49f477dbeb6386d783cb3a6180","0xf86d20b86af868098502540be400825208940b56ae81586d2728ceaf7c00a6020c5d63f02308845741bf838026a070af62c714808c7607ebe2cc756f20bed9790e5f5f20b192a83f689157a44bd0a0768a5d94766f1645e652dbef3826eed94074b5481a453ad12aa52ae6f8e42606"],"merkleProof":["0xf90131a06d62f4a7b42cf6729452fcae08b05731dfee28dae458f816c89e57ffeaa5c147a0e43fcb9750c4ca6b2edcceeca9f1f229422fd93bb18234648a9f17055eb2a8f9a04d140e4ef403bcb15429030bccad92459ac4178b8c929460473de9c412441089a03d46fc7ba9de3aa7823269232f06006d8a081dd6e454cf2e074a724b4024bffda0e2f94d34dc2af166d9dc5d633bbd7772b543cab746659352a3e3ea17dcecbbdca0d8263dd7869059f52e93ed14653a18edb2aae2403c4568c0db39419e030a1690a0cff0d0acd407ad79e570b7620f0dcc18adab15f0285080b6875d47f5acb3f937a01ffeb4235e305712d4c5b0ab0facca8f98f76da6044a4489e66070ea87184cd5a09764cf79d39a4ea9644e131b59c23b717c785aa9d6b967b17ba26d27625ac7fe8080808080808080","0xf851a0b022033d0b8c80ca6292d85be0981d41eee8df9b08e8b9a6b290d5efccbd460ba01cd0232ea3c15beaa979152d7138ce8773ebbe418783a70fdd83f90d798583b4808080808080808080808080808080","0xf8918080808080808080a0830827c187af66cbc39d20f93093d6527a0a25c4a4b2bf82fb231e3a04aec0c3a0e1e87b554ff61a9fc87e1546715934889e33cc3067a9660d2a94a52643c7540ca08ce688be748752375d8c8e5b635a19112ae7268041879ed0818e7d46b9c1f713a0890b5bf9539a40e77ecabf406f2d33cc94022ae7d3483c82a0d52b2e1c67dd718080808080","0xf90211a05902e6d28e316fa3355c75712cff36833028fc09f74d1d191fe05e2f3af16272a04bf7d9097d42c812b885d75f4c287b29960c636cd0b4a323c06e74b1c6ad98a1a088c0cdd525ae542fc92fcfeaa0f8a420948b2493415c2dca10eae22b0c3c1313a0031c44e08c34d5179602dfd3d63afcb504e2f35d10966659f39b5634b2e65a96a06618dd068c6f3c2dd8c62111d275134817c2d1bd46132cc6bfcb1493c8c84fd9a0352a72e7eaa5d3d5162b540d8ff3c4e172b9dc1b72361afe2e76d4fb86c57feda0c8f973f01bf2f87504347bef1c0fe6912e10fed3216b4b942e936cfe14da5026a057cad5c2eb30e9688abd2bdd47eccfa835c27dc2b9d1f99b51148f2958ce48ffa0913373a8b8dba5586d50c6e19549a7f9490618c8833c52cd42331b082aa9cefca0af6aeae947a0779326470e136fa0f71f751578f184bea1e84226dd5ac4144a48a0471cb27330f43b2d5ae797c439f99262b3666bcd5ce49a56a82ef2c8a7343bd9a094d690a5853840cedc2c166526cfb41d5f6d971c829e8c8a10287d258e6634b8a0218b082fdb8ff0ff66b897a8deab7817f08af0fc7ca16f8b6bfdb85bad95771ea0028a51575ce91b801195fd61eee8eb71f6d171b0dceb55046c1ac5a0e715e063a0175092f490ad4efe476654291ea39d45bfb8e646d7815f6fe4caffb9cab1727ea0b1c5995b3c27e97bf980c510b48ae499389c1ba606bf7a69d80e3d6e6d23870c80","0xf9011020b9010cf9010901838ac24eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":176,"signatures":[{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","block":9941955,"r":"0x367f8a584bfb2e9e78c4509ec9b25a91b626af4656412b421332aea07108be8a","s":"0x41803c879d96ff96c1dfd86f735d4a1c0dd2d0f148a8750ca817dcba07972262","v":27,"msgHash":"0xd41fdbf5c8e728149498aa95c0c962c7b1b208111376f9a2b27287febc15c9c0"},{"blockHash":"0x76a6a844183124aa536ceef06dae88413da4a27509d4dd91f5f3fffa796c04c7","block":9941955,"r":"0x9fab286a0d0011bfefa8828889e92868e28305ab411a247b54140052d835b0a1","s":"0x0bac8dc43fca7970db185f1823e5633401cae913a540fc9e4e6572b767925514","v":27,"msgHash":"0xd41fdbf5c8e728149498aa95c0c962c7b1b208111376f9a2b27287febc15c9c0"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":9942902,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":6470,"rpcTime":6153,"rpcCount":3}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","blockNumber":"0x2762db","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionHash":"0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd","transactionIndex":"0x0"},"id":1,"in3":{"proof":{"type":"receiptProof","block":"0xf9025ba003811fedae4ea5c2d69d010aee42f85fc52d1734a3403d68a82b63bd86baf5d7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07d5333691694496eaae51810c5e57a016c306f0f335f4b548ea8fcc45574a3f0a0bbb3ab701c45307f9e4556e7b6a0d3c174d842066d91e1c689737ae5242f7e11a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832762db837a1200825208845ea32673b86100000000000000000000000000000000000000000000000000000000000000008b2c88ca035a38a0753230ee0f1b28437f570b928351fbaba6bbd6d4a0735a7e34de2fa857e74afbcf472b54c3ead2801288741c88688b00d95642c41a9c3bab00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","txProof":["0xf86e822080b869f867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3"],"merkleProof":["0xf90111822080b9010bf9010801825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":0,"signatures":[{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x82457285707f9039b39e935d3b69a1b8efcc94d9a473e1383a41f65e5f92eba3","s":"0x047e4d4bd0fa3c96945bab372abf67001375d7dc9ce24519a2133d3afc8337ba","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"},{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x3f0c4166b5100c9cf84896a2da0e067e7a6a46ee66c88c60111eb8673046a2e5","s":"0x60cba2b7abd0c2bc5e32662b817a52c0a2c9663106f0c17bcebaa581292b227a","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":2581408,"lastValidatorChange":0,"lastNodeList":2561645,"execTime":473,"rpcTime":458,"rpcCount":3}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","blockNumber":"0x2762db","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionHash":"0x4456152b5f25509a9f6a4117205700f3b480cd837c855602bce6088a10c2fddd","transactionIndex":"0x0"},"id":1,"in3":{"proof":{"type":"receiptProof","block":"0xf9025ba003811fedae4ea5c2d69d010aee42f85fc52d1734a3403d68a82b63bd86baf5d7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07d5333691694496eaae51810c5e57a016c306f0f335f4b548ea8fcc45574a3f0a0bbb3ab701c45307f9e4556e7b6a0d3c174d842066d91e1c689737ae5242f7e11a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832762db837a1200825208845ea32673b86100000000000000000000000000000000000000000000000000000000000000008b2c88ca035a38a0753230ee0f1b28437f570b928351fbaba6bbd6d4a0735a7e34de2fa857e74afbcf472b54c3ead2801288741c88688b00d95642c41a9c3bab00a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","txProof":["0xf86e822080b869f867078449504f80825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf83802ea0196e11e25ec9de57108c7964753a034bb8f1dc02efdd1286b8dd865d21216dafa020ef4407a6d1c5f335ce5685cb49a039f704e32d139303576956ca5aaefc7ac3"],"merkleProof":["0xf90111822080b9010bf9010801825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":0,"signatures":[{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x82457285707f9039b39e935d3b69a1b8efcc94d9a473e1383a41f65e5f92eba3","s":"0x047e4d4bd0fa3c96945bab372abf67001375d7dc9ce24519a2133d3afc8337ba","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"},{"blockHash":"0x557d3b4da43f636d6449365a216fb70c76ec1acb2e98231158152e36e6a7b63d","block":2581211,"r":"0x3f0c4166b5100c9cf84896a2da0e067e7a6a46ee66c88c60111eb8673046a2e5","s":"0x60cba2b7abd0c2bc5e32662b817a52c0a2c9663106f0c17bcebaa581292b227a","v":27,"msgHash":"0x8fa680d5b9b087e0aa0ff3985fca7b433717e5fae34788e965f6eab5d11e62b8"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":2581410,"lastValidatorChange":0,"lastNodeList":2561644,"execTime":281,"rpcTime":263,"rpcCount":3}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'[{"jsonrpc":"2.0","result":{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","blockNumber":"0x114b55d","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":null,"status":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionHash":"0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4","transactionIndex":"0x0"},"id":1,"in3":{"proof":{"type":"receiptProof","block":"0xf90247a01ef625da39ab96124783516a110fc60f3760817acdd855a1605aa783c171f8bea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a4df255ecf08bbf2c28055c65225c9a9847abd94a0c1fbda7747cd2733e1344d765aa497cfb73a17b71f15de06ef5952530752ab37a01408010498362564b5c7cdea8ae1cb93be3bee5d9832447e16a11043ed88a289a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe840114b55d83989680825208845ea3379c9fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cde7b8416df595421b1d2c26cb476134b9c8e0feed3d5bde021e7f5aa43afe2d006f2ddc6d5c0b619bfcd0825dc45cd1768d9ba29783cdeee985fc25710c26cb4b6face300","txProof":["0xf86e822080b869f86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d"],"merkleProof":["0xf90111822080b9010bf9010801825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":0,"signatures":[{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0x7721c32e58634ef9ff58752acedb54269cb827c8909d024f5fa6c53bd94a42cd","s":"0x4785b591d5a592ae8c18c0c89700caa0193814589a167c0cd7206bcb700ff728","v":27,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"},{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0xbf4ac97d24925062f87074437dba9e7e7108731b0df65815150b9ab3a16e255e","s":"0x1e609d4e12d785e5b5ff4936460eab5eacc030e404163ebfde30df19c38ebfaf","v":28,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":18134431,"lastValidatorChange":0,"lastNodeList":18098311,"execTime":262,"rpcTime":242,"rpcCount":3}}]',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'[{"jsonrpc":"2.0","result":{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","blockNumber":"0x114b55d","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0b56ae81586d2728ceaf7c00a6020c5d63f02308","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":null,"status":"0x1","to":"0x6fa33809667a99a805b610c49ee2042863b1bb83","transactionHash":"0x561438bacbd058aca597dd8ebaafbf05df993c83c3224301f33d569c417d0db4","transactionIndex":"0x0"},"id":1,"in3":{"proof":{"type":"receiptProof","block":"0xf90247a01ef625da39ab96124783516a110fc60f3760817acdd855a1605aa783c171f8bea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a4df255ecf08bbf2c28055c65225c9a9847abd94a0c1fbda7747cd2733e1344d765aa497cfb73a17b71f15de06ef5952530752ab37a01408010498362564b5c7cdea8ae1cb93be3bee5d9832447e16a11043ed88a289a0056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe840114b55d83989680825208845ea3379c9fde830207028f5061726974792d457468657265756d86312e34312e30826c698417a8cde7b8416df595421b1d2c26cb476134b9c8e0feed3d5bde021e7f5aa43afe2d006f2ddc6d5c0b619bfcd0825dc45cd1768d9ba29783cdeee985fc25710c26cb4b6face300","txProof":["0xf86e822080b869f86780843b9aca00825208946fa33809667a99a805b610c49ee2042863b1bb83845741bf838077a09749142188e17306d3ddc3f524cc2c503538f3bbea10e831a91fba94d27a809aa04106cb2069e626ff8fec0429a95265dbc26dadd3641326089fb43569820a7b6d"],"merkleProof":["0xf90111822080b9010bf9010801825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0"],"txIndex":0,"signatures":[{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0x7721c32e58634ef9ff58752acedb54269cb827c8909d024f5fa6c53bd94a42cd","s":"0x4785b591d5a592ae8c18c0c89700caa0193814589a167c0cd7206bcb700ff728","v":27,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"},{"blockHash":"0xa7914036332015dc823c5514914916653f53edf9543bb31d44b2d96fdc037e91","block":18134365,"r":"0xbf4ac97d24925062f87074437dba9e7e7108731b0df65815150b9ab3a16e255e","s":"0x1e609d4e12d785e5b5ff4936460eab5eacc030e404163ebfde30df19c38ebfaf","v":28,"msgHash":"0xbbcd215bf4a55d481560d5aca421a030c55ea8618534b2176cf180a7496d92d8"}],"merkleProofPrev":false},"version":"2.1.0","currentBlock":18134446,"lastValidatorChange":0,"lastNodeList":18060209,"execTime":263,"rpcTime":248,"rpcCount":3}}]',
+ },
+ "eth_call": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308","in3":{"proof":{"type":"callProof","block":"0xf90215a0872116e89b76de63a05212ca21793254c12162f590191ec6cdb733f2062e0b21a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca08ce22a94575f9a881b4095ce6549992835e6675e8781fdaf0197b410768a00fda0b0473da62510452dd7afffba18c0fcae6393afdbbaa95c0edb067e5c58ea9bbaa0c5db56376954aa9939eb2215ab6dd167a098a7a4ecf7e7c796717fc6f3905e36b90100c04800221840480e400043c06002806c4000002c018c823a00c891014010052a3001102549450422400471020082030001018000100b2600005014b83839b12c4102000ad255c5080a00dc880500d60400091202138821402240d0b28784b07050e001440282080620117381402608301b70584c20c4418008860012202810400190410e09c00141018246502054a48d0805123108101414160218220074005812841680858100a0a9200082438009b08005c440a8428030a000004011052055400c08e230c04249b0800017100860880cc14236014400100168040011422620a09000040504180818a00800c030204049c08121a91080c0285b5200087420098707e4a4bd175da88397b6d28398466f8397b395845ea466d394737061726b706f6f6c2d6574682d636e2d687a34a0cb2467c20787d8a0d316f6e2bc7575e216defe9c6dbcab613113bcb130979f9e881a0f53b006e1ebb9","signatures":[{"blockHash":"0x6bf197c1ef0fe28fe59766876afb9b328f558df4c89663546bf499c75786331e","block":9942738,"r":"0x1922ed248444054658c007079a2333a7dfdb62b032f873bdacd5413af159d49d","s":"0x18f7a99a8140858513a66e7a3201ebf2656bcbb8062f40dc2950feb000c678b3","v":27,"msgHash":"0x40094a28bc67984d52be005db789dfb46fc3b491b46a26cdd36fe9d066ccbd17"},{"blockHash":"0x6bf197c1ef0fe28fe59766876afb9b328f558df4c89663546bf499c75786331e","block":9942738,"r":"0xc2c9330555e5d208965b7d6af8bfe20198535cd99a4f93c2a772fc5b5565deae","s":"0x4e54acad71ecabef80bb9bb8f89da29e2685da4fc88a6311b00259c7edc68095","v":27,"msgHash":"0x40094a28bc67984d52be005db789dfb46fc3b491b46a26cdd36fe9d066ccbd17"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"accountProof":["0xf90211a0e314bf209a9dfaee94b45b82e0f2d2b19934727eb0feeb06a2ecbd833e997e35a07c57296d9ef46aee570269000f954c965ea8b28d6b7a8572a51efe95290140d4a0382578e90c4dbc2ffedbdb4f28fe53f857340c991654a5c081eff9486908b258a066e02d1d74fdd5e11608cc03656c7ae5bfa11ce79c6656c108fdc89bfb267f10a00e0ce6187c4c50e0dc7a948b5a65aeb0189c9844bb9396af92fe89c9a4c93373a03bb2b21c7e881b87ca4b7061b703fb1d87cc82e87c74db2c28816ba14e286ce1a00ae900cf0494be66a0f9fc655be9ed414942766044704d5bf609683e1a083221a0e4366da2f34de89c5584ac1820427a1a4b33a04313bebb321b0a5e3b2f160ec3a0daad96b4608948ca3aabd20e3923dcf1ee0e899b1ccee5a82a8b44c1d8e59180a01eb455f5205f1c031a38958fa9aba581da5eaa979f35eb3801b224b6f9048702a024a3c74186159e69739a007303c945abd726c906147706f013fd4b0b10d90905a07c5531f1aaa25c10820de82fd1decff7dccc721a6e2f00d97035fef91b4556fba06e545fad27b83d249acb8c3561d747e3f0dbfe74c9927a95131b03a880dfbc24a0d54fd2e20e306ccea39ec6357be1cfa509992cd676a75ff6c15db70fc7c726cea0f2c60e7202fcb8fce15142846cf6a414f0c96b88a2213096199ae41d4715e30aa0c6e0f950b854f9978640eb81823c1178d85d70f1b6eede328ba85f37fe2d2f8680","0xf90211a0cd6f07095bf931cd907a1325cea08109fa27655ba565cc5c6c39512afe29b0cba00b56d70d6f948ea25d416c5ea5fb246503f37de2c90a51d645fd78f6d480dc9fa0eac5728609fda9215aae5cfd3a15eacea44536430ead85fab34f9bbdc0f2fc43a0a41f23cda22bf9d10127b2a7e6c4ba66de7169b36347c6f50ed835a757eb523ca0eb4366ef6f24b62cbfbd4993eff75507e45030c5e2dfb8b00b14a0d46c08ca92a0d53ecf6cff1db6372f911af214a3f114700e2b9288d5bb22fc3151bf210f47d8a0ec2fd0064dc5e05c3b7a6f1d8f7d5461f7e79f9c58cfd3e6cd9f5c7ccdaf40b2a0c50b88452d87f7228433d29b8ccc69dfceac64b1898447bf8709d97234c91d50a05257878f848c57ee272add59e005aa38027ce70fd9dfe718fb690d023bba4f66a060871eb7baed9267131b35ece93718ebd39568bfa4ab0a31531d57f7a3f6d0f0a0d8633d26f1a055a67c5eab2f67946f31c7e834bb96c55806e27e909bb2e5dd30a0b62519e97f570b355032329efed6846940e5036e67d37cf4f8e9857a601902b3a01a361c3871d8074185ca0a7dcdc74b3468e98d3e7d25fdadfc7f911ebb4f3a28a0d5424256d09d23f73f3a4a1617cf5c378b5acfd10819cd8a935c2b0640f0eefca0bbf7b59b246acdd390f68325fcc8f159cc688f79c682e83827a6d48eaa941bd4a0af1edbacb8a57dc89198340ef3afaa1d52496fb17efe9a70a467c15734c9318080","0xf90211a0810cd57be8a5e34efc87ee5eb2168d999920380a51649882f8c7caea25562bfca0dfb59b1c489fb4a1c36e08a251b29284aafb9007d8e6fc44b218e1a979191421a0d00e1fd8377dc4f044307708b39788a2cd87eb8c517db310bce2d876027cd1c4a002f1a56b4e9af014e195829db4cef65e66ad424f151ef2421678b32fae11ff89a0d65c1462b1152bdb007c78e9a2c52d18ae83a39ed4061cae2d47e720dd70cf53a0970aaf49f28b56d9b802f0d63df6d4007baf073acddc667778628c7c16948891a0cb517ae899d98b99072029b26076c37bb1e8b2c178d4b7653776b41be2691277a0fe5692d519cccd6e07b164f03975ccfd86807d0c0cd8179973110f6a5d3fdf6fa023351d20099b3590a363ae9076979b9ef0dbc8f6192766a1ca59132de9cca4bba0c6e8378f24f064f90161e04634af609569bad29c023fd7d0f1e8aa741248a472a0889c4a3b0b36c370f041c0ca2e81978a6af1dabc31e48d156798ee3b671a26bfa0eb4c229e597038779d57c00d555299b61d7eb3e5f0e2b5c46b38cb1709c3236ea01d3ce18b60d20d21059bd8a0667eebf2159b26eec256ad36cee1148f58a74a8da02e78571fc8d265a75eeae6151365702c9616341e60f678d45b689907684aaa97a01b918942298eec49ce660eb1a0d03cf8aa650dc81b25649119f64d8fc2c49f6ea03e1835f7218933385c7ac73d71ebf0278e051c3f8f2acf14adb617affcfe3e7980","0xf90211a0d35e84e98c291d53cede851d5cc1476020d0f8564f701b55347abb52476ea93fa04e5ba085a3dce5b88b541ee6c13aeb847829f3e1b169c8535115511f0c316ec5a03aec623f708e524d3acf46e242abc4fcf1178f275b437e0fa015807ecc9c5b23a02073f5b973742a2dedf7aaf0c32fbef0931d683aa2a135361001202ea731f17aa0f257514ae0ce8e1a8f74001ed6d3ab7486f92b487d8eff310c30487350efeddda09a735225b39600cf7ee84ce7590a911b8674afd680b07961bc785bf317ad7b58a0bef6d6bbce1dd0bef5dab0c34261b66e358b4418e349623908699f4853660679a0213fd8a18a6a284259f5869be460e515c258395fcdfb1ee764aae2b4b5ba4723a08038a4787eab0cd85e7f99bc109e913ff9c4e10d31008b792d7fd264f28e1732a0c2682c5a7a9a5e5ce87b101f37f3fca2a17188954c748d392160b2f15d04784fa0fc3c45f323e54d49e3c8da7e95be0186b740167f200388347f73689c6ef698f5a020e7ff1b310aa981b1d4cdf65e7781b683c974d89f282002864b59911a707e50a0cc02e0878f531040c339aba365d19ea09df47a352cf85f3adff175931f9a456aa02c2575a16d3508e6d2b8b060f119f7e3692caa0126a833c02d706726cea4a1aca0004163971a81fd213e90c958c101bff2c43dd85e587f626da9af9220b5492e22a0d478c7df2b1beb8f0c43d531d412a59c8d39e5029274e55afcf1076581c7299580","0xf90211a0caddbda2744ef6ca7ce78c8c42b1cf8e64361393ee44a3bae750fc8ab0feb5aca03f90fd9f328c8816d0fd15e4cc664ccfe10d5e2d331fdd745e64b2831990aaf0a0f0fbeb415948a5eb5704a6a298e6e8968efdbcbb4e6079c165dec1eb957ef0c7a08e91e46d98675bcc5d2e6ba6dbbe594a472635f9f770d5450a68e056c75b352da0ed449fb6298dd42c0d0988b42d2fc5c74d6b5d5cff4dca421d62ece60f554246a0e2e1b6d2a953f25bb783d105a42c9a6be19d07c7d19f71aa7f874f405a17d835a028c7112ff63d318c5c502b25ae2218e7503ee0f26aaca0a0a74500b85cc8b79aa0c6a5601599a9df66ac619ca9c11ed50da23903ca49e3763e8b37d767c4f57753a02173d1d1e2a98fe0e36a400c4809de35ec5cdeadf595dd18041f9a4561edced5a0a5ba811eed0b833f844988be3a21ac9756b61604f4157d64a26154dcfc1762dfa07c6df0351396276de731b2d46f2887234965cd6ef22e2beda956a58db84eef87a07d63fd72e40deae98cb5f7ae6cd5ed76459a9f3dcb53942f7743652743724c22a082293e94cb57aa391fb0a8a27f50fdc060272dfe054b0bf1fe5eed6821153793a0af0acc5af3e00748d0362cbb74100755e8dfcac7a45b1ea8185c384b7775b5fda0d6c810de8f7852ad3f85d25906ba106f57f0489a69cd403291c43169dd09bd7da0c2288d5e0b8834de1981563504867d94dbd32cc6f53dbe4bfda6facc6b3f45d580","0xf90211a03dc2949012be86f067afebe897c0ccd283ef5f1912710da9913c55ba3f795454a081bea4c6bd2e2026b5c6fdfa418b75662c7122d675f9a5b6415aaec3e2eb2a8ca0eda0d4ded108946c0375a17bd2f1985119a2f1fe99136c4084b15c5da010177ea0962c9bb5b52bb46492f6b43f76289c21c5dfb59983b4d4a9e26eef61f94e5b1fa0d5b2ab48bbd5d004d42b08d8fcb6d667b66e4764089b37ab5944bb1902218a46a0adf96f10cbd0242f4af39f240a5b52abf08311ce3014898e5359be8673fd0edea0522f2f81c49a9dde3af7c8f38facd88b99554bf9b3ca2cf7e3c159a1eaa0a4a5a0bbfb6bf77930ed25fb7123f8ac805ce42920746b6f4d6d9da85dc7479d6c50bba058ec4301ebc80d959f9eec90ef954bdabdf55975bbb5943a5ddaaa2ee3123549a04a85a0e52bc9da1ecd09e70cbb7baa759de8c7fc341f0b2ed68c1be5bc2821b1a009bb4288bdfb67f073711492801a2f9c4d719967eaea129a6de62b2d2e599d67a0a196adab721d52fb7c5b938e87692d1feed67ff9be6fd050f7a780a5ff08d96da09deeb4d161ba8dc2ff9d7098bd76ecfd548c52df13a1dafe39f7666c5e277cf1a0e53f585dd536d7f610a41dbba97b023e0660f0ab62c1eb009b273eeea98677eea0fefb9489bc053a8878a80aa198cebecbdc7e8c5f9dc7cd82c6a920cba96bdbe8a0f2ea87d62a695bc3c4936b9f503f9684334c044246acd1459105c3cf7d3b6bc080","0xf8718080808080808080a04a88e4063326e9f1c0149653f8da9056a293687e939d79212d94e4bc2b87260d80a04297cf3bb9d774bb05365c184d52ec92115082a2b613518e586cadef7c52a4c480a0eade1de7b508a295fa92bce9869b05a66f04682439332be4d1cb8ddb582c7ef680808080","0xf8669d3a53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a04a8ef46f838d98b214248fcb5142e829520b8ef5ea0ef7acf6545b2ad1433189a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0x4a8ef46f838d98b214248fcb5142e829520b8ef5ea0ef7acf6545b2ad1433189","storageProof":[{"key":"0x91e4e566080479b13e7a260eff22a914cf18cb4a9ed5d7b7e1b47f5ec0a1a498","proof":["0xf90211a0afdfe8760e697c382b4a117648d96293dadddc3c60edbab8db073ef661d23c4ba0b908849e84878697878920d9b8470d329416dc20b4d7be5beef9c8117431c71da0e069eeff65259206183efddfa2e6e88e01e119c5b4454f2f65b9e2be7a7646b3a09fca9e85c2c56f199a79c572e587e0186e722f116127af24e5b242c1689b18c5a08c6ffa2d67b2683e32f1f6f25ad587a9b3e70697abfd85e5afc70152377be05ca0308d387410feb7de6759f769e63e54817f4baf8907302120c9c0ab69bc5ed208a035b0f4e59687004d08b2459e80ac10709be16e3b9370f126c2f186435e37bba8a07e6b1ce8529ea3d77866ff16bf85de5043ff59a4c0b6284d114d9a70d71f9183a04c54ce3e0aa63f22711f36baf53bc6cf9b9e30d40bf3542c5ae461e9a097c303a0faa1eb0c6aee826c3c8569d6ae066f003337829c7b32de80bc54234f29ce8f76a00a9ab94f02ee60f4d7cb9f0b9fe9f49cf657009b721efce4ac92c23ae06d7199a0c6487e807294c4ef875dfa9ebedfe86117da753085d8e88075f6ec1aef6bee32a0125d529ecb6f4d208298d82fb16dae7665849e71527d783f90074f924ff928e3a0bfdb7271724c25d92e574b4426b9d5da94dc2e51b42e9268255c5d774f264ebda07043b66b6fa8729da83b742db2d5318749396f5e201493b423103c0bc9bc1e7aa0e97197a6c1dbc6189260008b0a60902dd0700358e8d6c4f0655d4b7823f0ade880","0xf90211a05c59c01164c132061cfdaca683a3c91dffb738f67d9c0ad45f011a5569d7e072a0eadd79b633693a3f8e390c049a0239b4201bbc82ee7e35a1aae25fde7fae9618a0147265ca7d147f7c8aca0e796f9c226d53148765dcd8dc66c0e41757499a8f2ea07794f750bc4564918767b7515b3166ca99be8b3a3456dce9a2b3a1168e718a84a05ae671928c964115b96c4d1b8f9786b0935c1f122e301b5b405986dffc0d02e4a077db58bf5f01aeb20e54344c87696c6b606b6f6d7869ee2935bbcc3cd783c266a02f24c432f6e307e2ea1bc86e081c6151c7a9b1d66c143381641563510f336ceca0ff8ea5aab8e1e85e5ac2a4f286db8cadec272b401ad6f9de216f63d22fb90aaaa0d454f19f6aaebd95a472e7258a348d62edd03ccca589ded6daeb41fd174dca86a0bad703d0e004cf730bf7cc6853a85ccdfa33a6eb4584750b9fa0b683351721b5a0027c2f5259c0fbc98e63b7f2402469f09591fe067c0b8d2b6e120cb995339112a038ddb699662a5d259c74b26339509b845303319df7f3dcaff59a412d776393a2a06a04090fd5aea9dcb76a81de68b036025e82ad3bf6cd899f49b34d147ff22735a047182a5cca874c56f0f5bea1a9a2797ff313af396aac2525e89030bde1372cc4a0a932a3465b5e2c84a3cc1740af01ababa2a68e8e0bf23b45b867262c3fa74676a0b6009d8bbf0d205c5412b4fffe6fa643cabbef4857a4ecdfb0aa07380aa67e4c80","0xf90211a05cd2ac7925fca79e50e32de66de8bc662c11ab7209df0bfd834407fc3c25e70ca07073d41a6c2bfb274632539186e846243af78e30a6a84ae194c877cd5be5c8fea09a0a167fee953021c5320e994191ceda14fb81ece5405fc1a0b6b3de88919337a037b4d6783b51ddd11f6ff34910527a1c853dfba52c2eefa7241f76a295c9b8aca0c56d935215be359e2105f67b5f2cd36a6f710bf0193db3eeb4d1075285a5af7ea001cabd651c52a50d5d94ce962a0509f3ae1aa4d06e6be3599399a15c4bec0723a07c0c5ddc9cc7de5d6d13e99e3a96d0c4528ea19b4fb1b630c1d4ee8b673cf7ada0fa6aae1e735ba228f203a0303cadbc58338286b19f15f2dd7635e50d9298771ca020df62d48dc3881311adf38f6ca2ed2288b9192121ab807fca61a3b28f9fda62a0f1dcf5154e87f63f189173bfb4339b4026fa47a0233ee6a1f8d6350247ebeda1a0ddfafc049fdb88a1a63bfbf3a7db2a43c230a1ab7fedb6910b0d5564a9cd21b2a0caa3e2d2072432cd207650cbee77a0aea6c0a41ed0bfd3c5ed41acd3f7d4db37a0deac3df28ccbc331dc3f603410446cc333c8d6042f5e21081fa285d7b8d58c88a08859542760d6b37d72c4ca6d40c91a1dcfecac50a3d9527bbba6b9f19b80cdc0a0da3459569322e69bd04f679d80b2e8c55036a5fbc1aa5c93fb505d18d2c8700fa02311925e452e0e5403ec2857dae70ee3d82401f07d470772ee65f6caf76a24b980","0xf90211a08332aea37ebc7817ad1cd64ffe4135bd3726d396440c420538d35025ff8feac0a0ab517d9c555fc6c7b599dab6fbd4d07cf3f422ba212a291ef229ec7e03825cd9a0d033096a80d4651dedcad822583fbcc3fa3d22f6ed278063de5126eef14b27cfa07166c532f0e793d4d2c695062d90c066b4d31bc25603b0045536c89e9e7ea5a3a021f1930ac29920713ae4631d5e6c7d679e9a237f998e26de4f266bd93c2f403ea01e4ef68c2fa17ec9d66ecef6a205220c120b4c16d9170278a313ed03be0c798fa0dd83b758df9cd13f966578616782cd67f2b78b932e6158dcae5c7609c148b157a037d7bd6ba46f1cac3af6c2c82ba38311540aa31c75648e2e167e1572784fcae9a02be4f3461c028608f894880dcebe4a73d42d39f41a54a2eedb633dc0d7b2e413a0d0a22ca8bcb1405bbce95db39b49f3a6bcc0c93f5558c484007dee7cbc792431a04ee0d5aea8f7c2cf3a495b56379ab5cd3721c395c6645c198347314921970bcda0b9e8dc3a4ad01b347d13a61846381f7eba4f45a3fe1c09478860a042359d691ca0a4e070000ca28ed0ab038a0be2f4e8313e8b8214becaf83cc2681d7e358547f8a005f430f77fd5f45812a4070cbf19de6a5d46f730799681787f3de2ad97bdae83a0282deefa0ea542c0b5546e6202cc4f6e56956df92cdae12e2e8f68f68bdbb7b9a0abed12dae5bba7e6a4e07f20d4e9d310a170e5197f56a3a6279dd77b042c1a7180","0xf891a0076ee949e888734bb55df1676d666e26753402c5fe418e1e921d98af35e9018680a0687b1faf792e40ae0e2c264059bd4cd2803aee270b139c5c9412f1cad066cf8d80808080808080a0bc8f4999a546a7bc6f32d40b3f6bcd1c3066035978661623b0a22289cff722898080a0fadc9abd062745cf492f54f92ac6a4239d55d0e7639298cdd053b223b8fedc66808080","0xf59e325a44ad6e63c5ca3b8679d5f154df97cc75bf475b0d4a226fcbf7a0b45995940b56ae81586d2728ceaf7c00a6020c5d63f02308"],"value":"0xb56ae81586d2728ceaf7c00a6020c5d63f02308"}]}}},"version":"2.1.0","currentBlock":9942744,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":209,"rpcTime":180,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308","in3":{"proof":{"type":"callProof","block":"0xf90215a0adc9c0d8809ab21ad0c77fa31a7df896f2333b1ee6aebc2f57fe6c8daf74957ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca046eea2648d2f523f7e79c71dc96e73c4eb2429be7de682c261ff19cdebdc5e95a0c2e744f66030a89ce7e6b4fdf820e4d3a4a8011c816201ff41cc381b7d195e32a09ea9c71cbcb10368313b2b65e722cda15198b7d13573e0fb55263fca1b8d1577b9010040908c0210004a180508d014808048183090102e560c088e007301200241003820983030888400c050050000050281241018a002c00124101a04c022283891144020092204a80010c1040d08c006e28c400a0a5e096422c0c0005abc02003260002080011b6417384481b18002a80825150010008855431002302410120408a095298148405a2c21080001018254268c300000088812308504d24011081c081026542700010400201654308102e02d0d01008004a00320202002488204203342049f0842a9c2006090288403402820cd000153309a94400921400010180e342884118c000102088886820a68813811c264448622041080cd850a2010005120428707e3a70c54aea88397b6db839843db8388c01d845ea4674994737061726b706f6f6c2d6574682d636e2d687a32a0cc4c52208871aeb5745e677a390be06c4d17ae8cb4069f140327c5f9d8a9652b887f9686b4073f1d2c","signatures":[{"blockHash":"0xacf3d2e8dfdb7a3d32ce815bdbfead9845ffceab31990e3c5a79754c6c418ab3","block":9942747,"r":"0xf6bf5ec24e714e973e50a8c33d58ef22194622b54b80d5ea0105c7b4ba91220a","s":"0x3dba783ee8f19912ccc43d8c67dde6973ad0ef87062401c0c6dd84e61bf2a44d","v":27,"msgHash":"0x7833f8f8973ed99ec0f124ab507ac2ab90531b6aab934d9c0919e68275a8f7d6"},{"blockHash":"0xacf3d2e8dfdb7a3d32ce815bdbfead9845ffceab31990e3c5a79754c6c418ab3","block":9942747,"r":"0xb359f1d8ce673fb44f326ba529ce66c1d33c3d86d54c1653b30e14c20d97729b","s":"0x096f016e19d8b29d821d9fc1bb9965ef8ce3eee7891138816cdb191b2a8d57b9","v":28,"msgHash":"0x7833f8f8973ed99ec0f124ab507ac2ab90531b6aab934d9c0919e68275a8f7d6"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","accountProof":["0xf90211a0a5d11650655bd0a70222aba5e77d65cee0f8f0383002452734b07db40c4317c3a0ea7f56b5ccfdc6271d08fcd1b229d361e56358c66cbdb9fcac878eb102796014a0048cf68e997ab5f9f055a71717870d163197cd69c0bd3ff60f64688bd4743879a0b1dd02a6a6581dcf0e3dac85342e31c8ab1b7e02076644ec98cce2d7dfc1015da06c2537940c506fc483596c9f2657be5d4a1adb77f88a536901921dcfcf4a2ec3a0cc098e9089c54dfa21bc9149ee16ed6bef021590d4552ed7a22a7d7f931d7b7ca04964085f2501194465f79829f8c4ed10c08d7e8284b9f354f3dbdcf8deb51442a041fc5ee85623e8ed611bfb2f51aecd1951aa5f644c86e4ee63b8a737d3a6230da087f2a352c5bed9767ed3dc52b7f7ad2a7fc3b2410836eab5ab7559dd103cb58aa099f200ed8b9696ccfe91575f70a1202d34e4e63febf0a2bcf52ba1b1de0d310da04971b22a5b41bd295464953642c37cf7bf8ce1dd3ecf5b3fc8f0497260c23d86a095da2b70fd5ef4728bf4d384992e5e5aefcaabec6f74cf3924dab410df7663a6a0090784376d7dbed0a8cfcfd435e82a60c38ada685212a464e405e77afe5c3555a01fc6c8333759d1e429ba8a0e5869b7dbd001172d3f573d09ee85df85c296586ea0a33724e1fc5eacd1387a62f70559910f8ebbec7ff088c7a1f8152d058cd37d36a01ae78340ba5c2e7774ffa3626a81cd6d357f5e42379979350f8269399fdcc37780","0xf90211a0879784e4934a99c3d4b25c1ec721b306a1d68f66332137c0ac6a27a9f4a9231ca0b58943b0aeeda81e79cdc1f4543df8a38973dcc54de473176c14518e65420b82a022da60db6e00057358cbd7c139a890a9950b36de4f4e4a44d6432317e6d500dba0bf5004bd0857225ee373a7f3b92fbb35953622756ccef78ded65afe1bb32dff4a0ff0cbf88cf040e91a3edbcc79ae59fac218e8ec92f285d31b8729ba2c1d2fd7aa0a7ded2bd3bc373f475a508cecf74180e01d78b64a99d739fe649d43beb621d06a0d1df1489e346f19500982b016de18e3547d21db4b366b4dc6b61da3006b09a06a06cebaf2a03d800985181981e3fde6b28abc38c3c5d7b765a20b879b841aad1e1a074cdc21d280c47159f8d658e7c21bbf9f8d162fd73f743d0f8c6107d9e9c4149a0f939fc878266c83b34e8835f5dd55b1f7459a8e8ff7cccb8e9a5d21ad951e4b8a06285007fb333c7409e608079b07e5ef83777c54dc7aa24935f99a9af9b95faf7a05fd0876ecfb3e0061c2c56f18498d03783b28de550951334f1a90e11f3db2e8ba0044ded054d4b335d61a8f0743a3693c3721bba4681ea0b45f9b63d432826fe7ba0d0faf94e88ab6a10045fd91b7efdc5ac929d5971dd685f26346b46fb4a1989b4a06d21faac6044ab72a09f4db6e35ec544e9d5de037556659741d622f240259b16a02420c111df3305251a3d8ca099970dc0761b3ad2d1db3d0c6aa20d6233b9051080","0xf90211a0810cd57be8a5e34efc87ee5eb2168d999920380a51649882f8c7caea25562bfca0dacaf0f89cf66b27694c64261aae6549402d3774c1a54d03ffd62d497cafa876a0d00e1fd8377dc4f044307708b39788a2cd87eb8c517db310bce2d876027cd1c4a002f1a56b4e9af014e195829db4cef65e66ad424f151ef2421678b32fae11ff89a0d65c1462b1152bdb007c78e9a2c52d18ae83a39ed4061cae2d47e720dd70cf53a0970aaf49f28b56d9b802f0d63df6d4007baf073acddc667778628c7c16948891a0c6b2b09fb65d02a44675ddd0abd2fceb60aa616a1abb20e39d0ebc0d88891c77a05e36af504cc12eb675ae1f94eab6015bd1991ec7c2c082df8d16f26d1e21f4b4a0e1d5118c0fc5b73c76d8f29c368428fef70181f7dc3f080fb1042c35daf24609a010ca5a5bc699568afa502196ba011036f67aa7b0dfad8dce62761653a2320b31a0cceb33ad446c6806574253e075687932bc6cfafd1eb593ca5c8e62a524ca2652a0eb4c229e597038779d57c00d555299b61d7eb3e5f0e2b5c46b38cb1709c3236ea01d3ce18b60d20d21059bd8a0667eebf2159b26eec256ad36cee1148f58a74a8da0368cf3e89e5cacd4dbbad31cb9658a5774d53dd003b4fc26241a1530677b96b4a01b918942298eec49ce660eb1a0d03cf8aa650dc81b25649119f64d8fc2c49f6ea0e53089d95ef2cfa6463861a4ee44b43d4745b85f0997aaf07bd79f9bbe12bbb880","0xf90211a0d35e84e98c291d53cede851d5cc1476020d0f8564f701b55347abb52476ea93fa04e5ba085a3dce5b88b541ee6c13aeb847829f3e1b169c8535115511f0c316ec5a03aec623f708e524d3acf46e242abc4fcf1178f275b437e0fa015807ecc9c5b23a02073f5b973742a2dedf7aaf0c32fbef0931d683aa2a135361001202ea731f17aa0f257514ae0ce8e1a8f74001ed6d3ab7486f92b487d8eff310c30487350efeddda09a735225b39600cf7ee84ce7590a911b8674afd680b07961bc785bf317ad7b58a0bef6d6bbce1dd0bef5dab0c34261b66e358b4418e349623908699f4853660679a0213fd8a18a6a284259f5869be460e515c258395fcdfb1ee764aae2b4b5ba4723a09e6d59610ec8234dc762a908340690c081fe551da4a90520590fcc2271bf6dbea0c2682c5a7a9a5e5ce87b101f37f3fca2a17188954c748d392160b2f15d04784fa0fc3c45f323e54d49e3c8da7e95be0186b740167f200388347f73689c6ef698f5a020e7ff1b310aa981b1d4cdf65e7781b683c974d89f282002864b59911a707e50a0cc02e0878f531040c339aba365d19ea09df47a352cf85f3adff175931f9a456aa02c2575a16d3508e6d2b8b060f119f7e3692caa0126a833c02d706726cea4a1aca0004163971a81fd213e90c958c101bff2c43dd85e587f626da9af9220b5492e22a0d478c7df2b1beb8f0c43d531d412a59c8d39e5029274e55afcf1076581c7299580","0xf90211a0caddbda2744ef6ca7ce78c8c42b1cf8e64361393ee44a3bae750fc8ab0feb5aca03f90fd9f328c8816d0fd15e4cc664ccfe10d5e2d331fdd745e64b2831990aaf0a0f0fbeb415948a5eb5704a6a298e6e8968efdbcbb4e6079c165dec1eb957ef0c7a0e8bdd431d05e4e85437d07519e41b421a5e202b93065afa866a639153c3c32d4a0ed449fb6298dd42c0d0988b42d2fc5c74d6b5d5cff4dca421d62ece60f554246a0e2e1b6d2a953f25bb783d105a42c9a6be19d07c7d19f71aa7f874f405a17d835a028c7112ff63d318c5c502b25ae2218e7503ee0f26aaca0a0a74500b85cc8b79aa0c6a5601599a9df66ac619ca9c11ed50da23903ca49e3763e8b37d767c4f57753a02173d1d1e2a98fe0e36a400c4809de35ec5cdeadf595dd18041f9a4561edced5a0a5ba811eed0b833f844988be3a21ac9756b61604f4157d64a26154dcfc1762dfa07c6df0351396276de731b2d46f2887234965cd6ef22e2beda956a58db84eef87a07d63fd72e40deae98cb5f7ae6cd5ed76459a9f3dcb53942f7743652743724c22a082293e94cb57aa391fb0a8a27f50fdc060272dfe054b0bf1fe5eed6821153793a0af0acc5af3e00748d0362cbb74100755e8dfcac7a45b1ea8185c384b7775b5fda0d6c810de8f7852ad3f85d25906ba106f57f0489a69cd403291c43169dd09bd7da0c2288d5e0b8834de1981563504867d94dbd32cc6f53dbe4bfda6facc6b3f45d580","0xf90211a03dc2949012be86f067afebe897c0ccd283ef5f1912710da9913c55ba3f795454a081bea4c6bd2e2026b5c6fdfa418b75662c7122d675f9a5b6415aaec3e2eb2a8ca02549d8801e8e983eceaf369008e3e566dcb9ec7619e91e28e3d443c2d1e148c3a0962c9bb5b52bb46492f6b43f76289c21c5dfb59983b4d4a9e26eef61f94e5b1fa0d5b2ab48bbd5d004d42b08d8fcb6d667b66e4764089b37ab5944bb1902218a46a0adf96f10cbd0242f4af39f240a5b52abf08311ce3014898e5359be8673fd0edea0522f2f81c49a9dde3af7c8f38facd88b99554bf9b3ca2cf7e3c159a1eaa0a4a5a0bbfb6bf77930ed25fb7123f8ac805ce42920746b6f4d6d9da85dc7479d6c50bba058ec4301ebc80d959f9eec90ef954bdabdf55975bbb5943a5ddaaa2ee3123549a04a85a0e52bc9da1ecd09e70cbb7baa759de8c7fc341f0b2ed68c1be5bc2821b1a009bb4288bdfb67f073711492801a2f9c4d719967eaea129a6de62b2d2e599d67a0a196adab721d52fb7c5b938e87692d1feed67ff9be6fd050f7a780a5ff08d96da09deeb4d161ba8dc2ff9d7098bd76ecfd548c52df13a1dafe39f7666c5e277cf1a0e53f585dd536d7f610a41dbba97b023e0660f0ab62c1eb009b273eeea98677eea0fefb9489bc053a8878a80aa198cebecbdc7e8c5f9dc7cd82c6a920cba96bdbe8a0f2ea87d62a695bc3c4936b9f503f9684334c044246acd1459105c3cf7d3b6bc080","0xf8718080808080808080a04a88e4063326e9f1c0149653f8da9056a293687e939d79212d94e4bc2b87260d80a04297cf3bb9d774bb05365c184d52ec92115082a2b613518e586cadef7c52a4c480a09f5eb31973a90aa4d0f2ccf693311fd8f0119d07efe0c69e57a1079b376e6fce80808080","0xf8669d3a53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0d5b065d61246743263f59c15301f6e0a33cca8e3cd8cd12499a7720bd47cd571a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xd5b065d61246743263f59c15301f6e0a33cca8e3cd8cd12499a7720bd47cd571","storageProof":[{"key":"0x91e4e566080479b13e7a260eff22a914cf18cb4a9ed5d7b7e1b47f5ec0a1a498","value":"0xb56ae81586d2728ceaf7c00a6020c5d63f02308","proof":["0xf90211a0afdfe8760e697c382b4a117648d96293dadddc3c60edbab8db073ef661d23c4ba0b908849e84878697878920d9b8470d329416dc20b4d7be5beef9c8117431c71da0e069eeff65259206183efddfa2e6e88e01e119c5b4454f2f65b9e2be7a7646b3a09fca9e85c2c56f199a79c572e587e0186e722f116127af24e5b242c1689b18c5a08c6ffa2d67b2683e32f1f6f25ad587a9b3e70697abfd85e5afc70152377be05ca0308d387410feb7de6759f769e63e54817f4baf8907302120c9c0ab69bc5ed208a035b0f4e59687004d08b2459e80ac10709be16e3b9370f126c2f186435e37bba8a07e6b1ce8529ea3d77866ff16bf85de5043ff59a4c0b6284d114d9a70d71f9183a04c54ce3e0aa63f22711f36baf53bc6cf9b9e30d40bf3542c5ae461e9a097c303a0c5f988c83de45a6baad074ae0de3f12c0369b2a646addc63abe6c655cf853280a00a9ab94f02ee60f4d7cb9f0b9fe9f49cf657009b721efce4ac92c23ae06d7199a01916d739ab6137ef60b707deaca64384b213779d12980d8291c22f796d5b65d3a07c353ff10fde0f5be0c4f4ef558c4e447c017a7d1e233f15991180ca7f22530fa057ebeda293c78f7bffebb9d4e37c31b422cd8f45b78cdf99c835ac913cf90c10a07043b66b6fa8729da83b742db2d5318749396f5e201493b423103c0bc9bc1e7aa01fa377f5c67102819adc1f95985343cfd12840a2d65825e262fc6759dfd63ec180","0xf90211a05c59c01164c132061cfdaca683a3c91dffb738f67d9c0ad45f011a5569d7e072a0eadd79b633693a3f8e390c049a0239b4201bbc82ee7e35a1aae25fde7fae9618a0147265ca7d147f7c8aca0e796f9c226d53148765dcd8dc66c0e41757499a8f2ea07794f750bc4564918767b7515b3166ca99be8b3a3456dce9a2b3a1168e718a84a05ae671928c964115b96c4d1b8f9786b0935c1f122e301b5b405986dffc0d02e4a077db58bf5f01aeb20e54344c87696c6b606b6f6d7869ee2935bbcc3cd783c266a02f24c432f6e307e2ea1bc86e081c6151c7a9b1d66c143381641563510f336ceca0ff8ea5aab8e1e85e5ac2a4f286db8cadec272b401ad6f9de216f63d22fb90aaaa0d454f19f6aaebd95a472e7258a348d62edd03ccca589ded6daeb41fd174dca86a0bad703d0e004cf730bf7cc6853a85ccdfa33a6eb4584750b9fa0b683351721b5a0027c2f5259c0fbc98e63b7f2402469f09591fe067c0b8d2b6e120cb995339112a038ddb699662a5d259c74b26339509b845303319df7f3dcaff59a412d776393a2a06a04090fd5aea9dcb76a81de68b036025e82ad3bf6cd899f49b34d147ff22735a047182a5cca874c56f0f5bea1a9a2797ff313af396aac2525e89030bde1372cc4a0a932a3465b5e2c84a3cc1740af01ababa2a68e8e0bf23b45b867262c3fa74676a0b6009d8bbf0d205c5412b4fffe6fa643cabbef4857a4ecdfb0aa07380aa67e4c80","0xf90211a05cd2ac7925fca79e50e32de66de8bc662c11ab7209df0bfd834407fc3c25e70ca07073d41a6c2bfb274632539186e846243af78e30a6a84ae194c877cd5be5c8fea09a0a167fee953021c5320e994191ceda14fb81ece5405fc1a0b6b3de88919337a037b4d6783b51ddd11f6ff34910527a1c853dfba52c2eefa7241f76a295c9b8aca0c56d935215be359e2105f67b5f2cd36a6f710bf0193db3eeb4d1075285a5af7ea001cabd651c52a50d5d94ce962a0509f3ae1aa4d06e6be3599399a15c4bec0723a07c0c5ddc9cc7de5d6d13e99e3a96d0c4528ea19b4fb1b630c1d4ee8b673cf7ada0fa6aae1e735ba228f203a0303cadbc58338286b19f15f2dd7635e50d9298771ca020df62d48dc3881311adf38f6ca2ed2288b9192121ab807fca61a3b28f9fda62a0f1dcf5154e87f63f189173bfb4339b4026fa47a0233ee6a1f8d6350247ebeda1a0ddfafc049fdb88a1a63bfbf3a7db2a43c230a1ab7fedb6910b0d5564a9cd21b2a0caa3e2d2072432cd207650cbee77a0aea6c0a41ed0bfd3c5ed41acd3f7d4db37a0deac3df28ccbc331dc3f603410446cc333c8d6042f5e21081fa285d7b8d58c88a08859542760d6b37d72c4ca6d40c91a1dcfecac50a3d9527bbba6b9f19b80cdc0a0da3459569322e69bd04f679d80b2e8c55036a5fbc1aa5c93fb505d18d2c8700fa02311925e452e0e5403ec2857dae70ee3d82401f07d470772ee65f6caf76a24b980","0xf90211a08332aea37ebc7817ad1cd64ffe4135bd3726d396440c420538d35025ff8feac0a0ab517d9c555fc6c7b599dab6fbd4d07cf3f422ba212a291ef229ec7e03825cd9a0d033096a80d4651dedcad822583fbcc3fa3d22f6ed278063de5126eef14b27cfa07166c532f0e793d4d2c695062d90c066b4d31bc25603b0045536c89e9e7ea5a3a021f1930ac29920713ae4631d5e6c7d679e9a237f998e26de4f266bd93c2f403ea01e4ef68c2fa17ec9d66ecef6a205220c120b4c16d9170278a313ed03be0c798fa0dd83b758df9cd13f966578616782cd67f2b78b932e6158dcae5c7609c148b157a037d7bd6ba46f1cac3af6c2c82ba38311540aa31c75648e2e167e1572784fcae9a02be4f3461c028608f894880dcebe4a73d42d39f41a54a2eedb633dc0d7b2e413a0d0a22ca8bcb1405bbce95db39b49f3a6bcc0c93f5558c484007dee7cbc792431a04ee0d5aea8f7c2cf3a495b56379ab5cd3721c395c6645c198347314921970bcda0b9e8dc3a4ad01b347d13a61846381f7eba4f45a3fe1c09478860a042359d691ca0a4e070000ca28ed0ab038a0be2f4e8313e8b8214becaf83cc2681d7e358547f8a005f430f77fd5f45812a4070cbf19de6a5d46f730799681787f3de2ad97bdae83a0282deefa0ea542c0b5546e6202cc4f6e56956df92cdae12e2e8f68f68bdbb7b9a0abed12dae5bba7e6a4e07f20d4e9d310a170e5197f56a3a6279dd77b042c1a7180","0xf891a0076ee949e888734bb55df1676d666e26753402c5fe418e1e921d98af35e9018680a0687b1faf792e40ae0e2c264059bd4cd2803aee270b139c5c9412f1cad066cf8d80808080808080a0bc8f4999a546a7bc6f32d40b3f6bcd1c3066035978661623b0a22289cff722898080a0fadc9abd062745cf492f54f92ac6a4239d55d0e7639298cdd053b223b8fedc66808080","0xf59e325a44ad6e63c5ca3b8679d5f154df97cc75bf475b0d4a226fcbf7a0b45995940b56ae81586d2728ceaf7c00a6020c5d63f02308"]}]}}},"version":"2.1.0","currentBlock":9942753,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":374,"rpcTime":130,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"jsonrpc":"2.0","result":"0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308","id":1,"in3":{"proof":{"type":"callProof","block":"0xf9025ba0483045ddf06bd227e4d2d75b3cacb9366df90de097589f151e7d56bc2e9369c0a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0d100a67f24625d11cf1260ac42444380dc72c7fa282e6ae7c401f51a14daa09fa015ccfb71a230e02f060f35b6caf085b57759af087ebbdf1c52697874b4f4f7bca0a016a3e03d190d68ed522721348ab73e351de580cfe6cc0599c1ef3ce4e970eeb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832779a8837a120082520c845ea47c80b861506172697479205465636820417574686f7269747900000000000000000000001241cda8d03038a95930cb8dfb9aa9e87e72a379a9a3e15ccf07ae5e6b8e69175c5954920ab7f4aec496488da2763c25b08951156ddfd5b6c3893f928d6cf8e401a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x71e0366e15cdae663cbc4209511b1c941edb2e8b26953d7396950b3a85193681","block":2587048,"r":"0xf283c403609a18e772cbea601012725c44501d859d5956f1856a44b19fdac255","s":"0x2d1d76709c5236c4d19214bee69ff8c3222688a7c95c9936a8127c6124b2748d","v":28,"msgHash":"0x42905bc0b839c58ad383864e422ed119c893052b5c60417dd74c840bcdd79a36"},{"blockHash":"0x71e0366e15cdae663cbc4209511b1c941edb2e8b26953d7396950b3a85193681","block":2587048,"r":"0x842ce2d5c9db929e35366bf58be6c8caf84fe2174a27edfc1f88c6a640340bea","s":"0x2a9cbdb8f2a23fc39cb8394cc42ac5a096f7f7989df321172c64592f7abc3abd","v":28,"msgHash":"0x42905bc0b839c58ad383864e422ed119c893052b5c60417dd74c840bcdd79a36"}],"accounts":{"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e":{"accountProof":["0xf90211a0b854e6e76c51c35e422dc68169f6c5f21040fd23deac804a4c1c726c9d7a8837a09d44fa2c8a4d785feb36f85c1ab350e3284b82ad73ff6d330624a0db0bfded39a0b73aace252b51a5126673ba099412889ae900334a24b45fd4ba8851af892d28fa041890464b3971d73ba0d05be11ad87e3b607373dd148efaafcdcf686487456e2a09ca3e80ac03c07610e6b0c95d4c8c174e7631bd4a2d9f69013d4882472e2dd39a097c092f97b9a58a147423c6d6ec2c57fc551bf985f5305254b1dcfcac1f0ba01a00eac9c76024834ade8589d1386a278dac4f378900060f256251b7c4afa30147ea02fa73a520eec0b60c4eb5b63c59c74b45da4a1ec4dd3dab5425b2a31aed0e9fea07c5ddd2d1a6ca44447e5ea1ab9d0c3b2cb74038804f5e544f136ade580d298d1a017fc67529a8840a6aea4451337124739b66f1a0012806904fa07012071e97d2aa0a4e1ad538782effd32ae1573e7b2ca7399a6e8c7b7fd3b4d0fc5018d1c946a1fa0f31d5e3448e19d463713b2bd64d619cce3384f5437cb8414ca6c03c77578706da01b8fbdd07b29a1d922939d2bddecbcc57f7fb3a9821f539d7152def9cb9eb46ea0ee2f40e22c38e39dce384d30affcc8c57f593bdd9395509744716811d1680025a0bad83eb1b021350e2d716f1b5a9c8c2e05f8f3ef63aa4b1835d2ecec49750d77a0a001698a053d24e6f26c45247e449a48483b390ff803229277a5669e947c682580","0xf90211a01fee7969cf4ade500086fc8b85acaa52f0c2df5996866a50092c99e64462a40da0ed8c5d23edd7b9118dbd40f23286222927479ab7c46cba02fb3c7e6a4f3802b5a0e4d88df720993b5214761217a6f692636a175cd68afdbdb28810f58b1a6fb0e8a0b50b79fa9186646ca175a7ab32f4103d1273b5fd4e1e455020a5ab9e27541d9fa0ba0fb4c575c2263c7f5bc12d2dc32566f0f45c2907c2452160a6243d98c5e359a0c7c9ee54e08d27465cd96c438ba06c1bdd41f8c4c1c535d3cab1013372995b8ca045184cd142f6b4e085ba7a12f497392988858793e097e62dd8006b62cc2d40e0a0fde8599551f5bbb9ee48ebb44647310237593113fa5bd6279b363658a56fd569a04af1b78f7369cb80d294b816ef4150dac587e74b5e4fd1d694ccdc70f7b8dae9a0927c123f2b85b1cc36dadc9a7480bbb0f340f55106a7a191bebb4c02a80eebfda0a034cb59a553fbf3ba6e99ece8c26ba49eacf884ebec419785305aec312746efa0d431d1895f12cf91a594383bfb97743e34f0ad2f0f40269e7183ad8a8e3862dba0c2a3691c28c0547264a4d39ee81c4ce8e7826f2013e5b20a2d74d2efd935a44ea08deecacce3e0145aa8590ac58333cd5789024e4bd0cd927853f6198885a82d2ea0022f54fd50be1b7133344374032c146a276d5e68f1c1e9279f04c8c7f9e69120a0d37b2c683614801ddf9a63ef70eab7035afae663229d94e28c428ec6acb9be0880","0xf90211a0ce97293c34549170171bb723390dd47dc53b8237186c1dab1e8c578f181da75ba022c74c0c055f141c9ab5e43754f8dcd806bf80ae7f9280ed841880ba88f41f95a032105d2b5c182771994280ab031f650a6a8cdff20949d04cccad7b46130f913ba0d0f1612ff9f1d9436340ad0d65f68fb5f6df1e2faa764c12af5a9ad96d62761da0b4e8682ab002a59733edf9d308315f88797c6b87c24c9bbba8c56822533d19c9a02f2a237d03b62784f82c9c18405494ed771ea12fcac9b1329e9830ba3ae8d710a029aeee66e4afd9f9bf4433a02ccbb7b2f56d5e8745d0d63c40d5c23dfe75de4ba0d0211b072f1382dac5de0b3d6fcf2b6b52ecdb3cf72d798c09058665c361940fa03f8df8c9f0a9770e8fdeb3d162e2b74d38f2cc8de3e7f776d7a5b24c0408d25da06f1b88bce40ab519418a821f918d9b8006dc165b13e1551209756bd35ea1867fa01796b1002df593ef8c02a9c4b7b07b7003710512f31a964e0c5de0339f95061fa0e70a10f60c513e3ea2ed418df7fd1c70e6a74971edf6cc65cce9dd5217c5766ca067f3b37f5f1ba9862694b0707203e5ae79e3bca5c5b6194ddfbdcae38096d736a0e03870853881d3fec38abc662478cedbe84669b510433b073fa902e99985f586a05a30f44daa3205e3c7ef8a4a42517bc72f7a09757fdd534dac361bef3f7b38ffa048e32d9f5c0722c908fb1ec3c60094a15bbfc5be673847531f16527f4c651fb980","0xf90191a090180abf51ee9a8d06b322766f3cf17aade5f5606d54fc17844f062a105e4aab80a09fd4239f754ce994e3f05c29b0800c8fa29ea7476f3d1bb33afcc3b33029b04ea0c32c2ce9a42b69f26eb54ccf4f397f9fa5c64b1289972e00f5df914f3b867d8ea0339ffbbc8b267ba43b478c855cf7c3b65b5681198dbe14a6c383d6e927fb99f1a075f2e6febe371c57c91644ef405b342b831264580cf994fd94c7d42ae554ae9aa0c95784b61cd7b153e42c8e22d91028bcd9b7a440e8bed87d5f54cbfea185b05a80a0918bbbebb389e4c100248c7d1ce4df01aeca2e2214cb89f4c3050d73efdbc28c80a0d8dff14cd8d20fe86f1abcc1d12cc7004b5d82af5fa65b16c6593d6ae3e35d76a04b75c24381c9c971ab560c96baf1e65128510c2a7c71e73b7c4533424eb376d3a02933b22375eaa4148e5cf2f687209eb60f9fc3c93af79e7d09bb7a483e5c922380a07caa3f3785c08bc622dbd2b81f4437c95467a9f137a0e83ece5c5c236cbc03caa0e1f6bc975a6f522766aee88f41212e45ff4519a197cd665fba9421b0242d8bcf80","0xf851808080a0b11c6b2f2d89847435e8696888779533b8556adb7a26799a95a4fe4396868de8808080808080a004765232d3d7c62b886a9855d8074b75a2b597b4dd7ad2e964ed0a0642cb1266808080808080","0xf8679e32ca53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0a36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xa36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69","storageProof":[{"key":"0x91e4e566080479b13e7a260eff22a914cf18cb4a9ed5d7b7e1b47f5ec0a1a498","proof":["0xf90211a0c1cff81b485e3970533d03904137bf530668c2fe43484512568a0718b776049ea0b5f6f3e007520ebe206bf3f44eed8189c4e7bd98e965b2c4aae39200994ef6f4a094f51882958f9f01740614a7e624e6b679686e376a5d3f348a62b0688ffe4250a02c6be05247b7038fd41dfaa28f9202f1752500bc2ffbdd1df3462d7c21a7909ba090f4ce06d9c70a1544240692a2f36265bd34da3928e5185ba183ef8d9c18ca22a0c141573e904584b31e9ac45ebbddb46e4006176ed393a22071d94ea3255089daa00d3f247bdea5d45dd22966cb4772fc8430e602e3db2d9a37d541eb377240d0afa02cf9af56a3f0f2c30a0659ca905c906d4178707c5a4cb2530de9ac7613b0686aa0dd08fb62161b9771647a98cf8ff1c9e735c9c712795ef0c564f3be4a1498f6d8a0dbc26012bbaea11ce63400d6c319a517af82b4c1d7defc73e5f52d53ccfef201a0df21b134664d0a6d6c9320797d35b5ede85568c93ec594e9ab61ef9994c6f2a0a0c3ef633aec0a4a63d3bdf186a972995bf281c1211717741ae514bb914c5c6519a005c9248531c60761d86358914dc354b4edb87ea35ef526057f1a5897de4cd1cba078bc36f8dbc8db7245bb3290330dc81337a42418e6d82720e2883807b74d5803a09c78d063549ad17add128dd4324a98cd93b58bb70435b3e211ebfb9210db8422a02cdf2887c1c85af2961183ca34694903a5c85c93e38ef79b00859e3a6e81b42b80","0xf90211a0b923085dc78cf2ab0489315cfb0ebbe76c1d9b38bccaf3b5be06b48095aface5a0afc98f44a9e63637d188939b5e6ea342cf6fb042883ddd564f3fe657bb90756ea01c9e6091834f76a0f72731d982c522cbd9195f6f05001317ba88eaa7413f68fba01e5351421921b78a451f898dd7f89b7da2f6c0f29668dcba7bc46e49e1a4d254a039a8a2df8c0aa3b7f7e980004a04230787a28fbb6eca917382aa37390b4d7cf3a063686765435e064f4246b9ffbba262a9eb2708ea547db82b8efbfd2d65772018a01e8c5728b0ff9fb7e3f1b4cba5faa32c9067d34b2a35127ba2da501cd570c851a0bb226a1f610bfc3b58a814cd926c4a74140186b24d9e5a0ab775c072460ae068a0a1c27fd2ed0f15f75be505b80a8136b6fffbff3a9cc8a1cd681c9c79d9f644d1a06e66ffe0c914582a7ba628d74be61e6b5ffe99fe8b248105ce484a2d06725e41a09f95e9b8c6d8260b98c2f1acdb8d50c7d68a26d75152e00945e3b84ee90a3fbba08b8553a262a402651fa11765213bb63d4a2819ada913cad52b12c6ad697d9a46a0bc2d134e58c418102e3d7bbd1f4b834e0037408d0e668b3eba2f2a12f4bd78cfa0b38bebc75096c2d1d08d2012339976310d2c69984cabfd41c287e99345139455a071ea33dd5e9ed9f0afec7e86d70b3a250e1f5e9258a50ac6b62f6bf4774a18f1a074f3e83ce60fc75814f18e2c4a5f9e7433c6b1434402038c555751de249c153e80","0xf8b18080808080a0716dc2349a67d75533815556083f876fe23b5ed8fb49477ae77f75dfad0c5c2d80808080a0c328f972c8372d609366404f9868982546f23dc289fbcf66fbc070f654bca4af80a0205c16975897cf330ce42d27ef1cc74bd26748b176900f737cec5edb80ecd6e380a0a487e20e97ab9f735c3bcbd8b703208e0c8549224adbc1707eee2bd1c28b62a2a0f7932cafbe50458d0a254495af4624dea0e1091890145cf5ad9005be91f746e980","0xf69f32025a44ad6e63c5ca3b8679d5f154df97cc75bf475b0d4a226fcbf7a0b45995940b56ae81586d2728ceaf7c00a6020c5d63f02308"],"value":"0xb56ae81586d2728ceaf7c00a6020c5d63f02308"}]}}},"version":"2.1.0","currentBlock":2587054,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":155,"rpcTime":131,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"jsonrpc":"2.0","result":"0x0000000000000000000000000b56ae81586d2728ceaf7c00a6020c5d63f02308","id":1,"in3":{"proof":{"type":"callProof","block":"0xf90259a0b70b03a6c60d9b6c0059e80c8e49f60c49bffcf1742c71f6a3c66bf7a00e8fd1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0172c424ce99b486dbc06e8de514339ce3ad1ed65fe6b2b53360e233eceb38e5ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002832779ab837a120080845ea47cadb8610000000000000000000000000000000000000000000000000000000000000000d55aa2ab1b067e5c9d28a81dcbc2cad3c4896acca09e8db03d80a37a042e2c8176f267c1e365d1dbfb83918fb63127c72b332528b2a383d9c56b3bbda09a0ae800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x4663d5290fa2c797301b535158f4ec004c5b59b06bb76095a1db2bc55ab5ba29","block":2587051,"r":"0xfdd52455244b9b3fb22b3c799862af0082bfae1a4bce8d3b2f1f6c32b3cd50e8","s":"0x38b019ef2c0c4824b622f8624c9e47e6042d042354a2780c791358e067438a16","v":27,"msgHash":"0xad8d209303fb10ff34a81b31685d252e1dafb7fff069f7709ca259e1dd69b692"},{"blockHash":"0x4663d5290fa2c797301b535158f4ec004c5b59b06bb76095a1db2bc55ab5ba29","block":2587051,"r":"0xc248c8653a4c89065a2c2f4aa832c130891374b21d38a2d68b5af576fa293bea","s":"0x1634bcb4b5d2767f55a09f5f651dfbb9020ca24b865af9e30e857a1fd363c1a0","v":27,"msgHash":"0xad8d209303fb10ff34a81b31685d252e1dafb7fff069f7709ca259e1dd69b692"}],"accounts":{"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e":{"accountProof":["0xf90211a0b854e6e76c51c35e422dc68169f6c5f21040fd23deac804a4c1c726c9d7a8837a09d44fa2c8a4d785feb36f85c1ab350e3284b82ad73ff6d330624a0db0bfded39a02f364d0ccc4f2b3820ea2b5e28cc94725396a1971c42cbd3375f393fd867511ca041890464b3971d73ba0d05be11ad87e3b607373dd148efaafcdcf686487456e2a09ca3e80ac03c07610e6b0c95d4c8c174e7631bd4a2d9f69013d4882472e2dd39a097c092f97b9a58a147423c6d6ec2c57fc551bf985f5305254b1dcfcac1f0ba01a00eac9c76024834ade8589d1386a278dac4f378900060f256251b7c4afa30147ea0981a8ac7e902ecc1a364dc58fcf3d2722419d4fb25ae87aa97d2ef0a97589982a07c5ddd2d1a6ca44447e5ea1ab9d0c3b2cb74038804f5e544f136ade580d298d1a017fc67529a8840a6aea4451337124739b66f1a0012806904fa07012071e97d2aa0a4e1ad538782effd32ae1573e7b2ca7399a6e8c7b7fd3b4d0fc5018d1c946a1fa0c2da4fe50085ece2f10407e86edab7f7d202f0b0c7927e11ee4bcecd0a057c1aa01b8fbdd07b29a1d922939d2bddecbcc57f7fb3a9821f539d7152def9cb9eb46ea085bb4fab1c4086a5ef3063f7763e558a595c3158ff9c56116267f5fdc3758295a086044a210b5e53cf536f4eb19469ac751f6d91ed26aa9182ecdd4507cbb57c5ea0a001698a053d24e6f26c45247e449a48483b390ff803229277a5669e947c682580","0xf90211a047e60e68f6b34a86505c9c15cc87970def109527fb91f19dbbb7305608d75987a0ed8c5d23edd7b9118dbd40f23286222927479ab7c46cba02fb3c7e6a4f3802b5a0e4d88df720993b5214761217a6f692636a175cd68afdbdb28810f58b1a6fb0e8a0b50b79fa9186646ca175a7ab32f4103d1273b5fd4e1e455020a5ab9e27541d9fa0ba0fb4c575c2263c7f5bc12d2dc32566f0f45c2907c2452160a6243d98c5e359a0c7c9ee54e08d27465cd96c438ba06c1bdd41f8c4c1c535d3cab1013372995b8ca045184cd142f6b4e085ba7a12f497392988858793e097e62dd8006b62cc2d40e0a0fde8599551f5bbb9ee48ebb44647310237593113fa5bd6279b363658a56fd569a04af1b78f7369cb80d294b816ef4150dac587e74b5e4fd1d694ccdc70f7b8dae9a0927c123f2b85b1cc36dadc9a7480bbb0f340f55106a7a191bebb4c02a80eebfda0a034cb59a553fbf3ba6e99ece8c26ba49eacf884ebec419785305aec312746efa0d431d1895f12cf91a594383bfb97743e34f0ad2f0f40269e7183ad8a8e3862dba0c2a3691c28c0547264a4d39ee81c4ce8e7826f2013e5b20a2d74d2efd935a44ea08deecacce3e0145aa8590ac58333cd5789024e4bd0cd927853f6198885a82d2ea0022f54fd50be1b7133344374032c146a276d5e68f1c1e9279f04c8c7f9e69120a0d37b2c683614801ddf9a63ef70eab7035afae663229d94e28c428ec6acb9be0880","0xf90211a0ce97293c34549170171bb723390dd47dc53b8237186c1dab1e8c578f181da75ba022c74c0c055f141c9ab5e43754f8dcd806bf80ae7f9280ed841880ba88f41f95a032105d2b5c182771994280ab031f650a6a8cdff20949d04cccad7b46130f913ba0d0f1612ff9f1d9436340ad0d65f68fb5f6df1e2faa764c12af5a9ad96d62761da0b4e8682ab002a59733edf9d308315f88797c6b87c24c9bbba8c56822533d19c9a02f2a237d03b62784f82c9c18405494ed771ea12fcac9b1329e9830ba3ae8d710a029aeee66e4afd9f9bf4433a02ccbb7b2f56d5e8745d0d63c40d5c23dfe75de4ba0d0211b072f1382dac5de0b3d6fcf2b6b52ecdb3cf72d798c09058665c361940fa03f8df8c9f0a9770e8fdeb3d162e2b74d38f2cc8de3e7f776d7a5b24c0408d25da06f1b88bce40ab519418a821f918d9b8006dc165b13e1551209756bd35ea1867fa01796b1002df593ef8c02a9c4b7b07b7003710512f31a964e0c5de0339f95061fa0e70a10f60c513e3ea2ed418df7fd1c70e6a74971edf6cc65cce9dd5217c5766ca067f3b37f5f1ba9862694b0707203e5ae79e3bca5c5b6194ddfbdcae38096d736a0e03870853881d3fec38abc662478cedbe84669b510433b073fa902e99985f586a05a30f44daa3205e3c7ef8a4a42517bc72f7a09757fdd534dac361bef3f7b38ffa01e474a8d9a5d65a08bcd408146b4d5960f5c04f6220ded4375cc1f35c3b0483b80","0xf90191a090180abf51ee9a8d06b322766f3cf17aade5f5606d54fc17844f062a105e4aab80a09fd4239f754ce994e3f05c29b0800c8fa29ea7476f3d1bb33afcc3b33029b04ea0c32c2ce9a42b69f26eb54ccf4f397f9fa5c64b1289972e00f5df914f3b867d8ea0339ffbbc8b267ba43b478c855cf7c3b65b5681198dbe14a6c383d6e927fb99f1a075f2e6febe371c57c91644ef405b342b831264580cf994fd94c7d42ae554ae9aa0c95784b61cd7b153e42c8e22d91028bcd9b7a440e8bed87d5f54cbfea185b05a80a0918bbbebb389e4c100248c7d1ce4df01aeca2e2214cb89f4c3050d73efdbc28c80a0d8dff14cd8d20fe86f1abcc1d12cc7004b5d82af5fa65b16c6593d6ae3e35d76a04b75c24381c9c971ab560c96baf1e65128510c2a7c71e73b7c4533424eb376d3a02933b22375eaa4148e5cf2f687209eb60f9fc3c93af79e7d09bb7a483e5c922380a07caa3f3785c08bc622dbd2b81f4437c95467a9f137a0e83ece5c5c236cbc03caa0e1f6bc975a6f522766aee88f41212e45ff4519a197cd665fba9421b0242d8bcf80","0xf851808080a0b11c6b2f2d89847435e8696888779533b8556adb7a26799a95a4fe4396868de8808080808080a004765232d3d7c62b886a9855d8074b75a2b597b4dd7ad2e964ed0a0642cb1266808080808080","0xf8679e32ca53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0a36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xa36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69","storageProof":[{"key":"0x91e4e566080479b13e7a260eff22a914cf18cb4a9ed5d7b7e1b47f5ec0a1a498","proof":["0xf90211a0c1cff81b485e3970533d03904137bf530668c2fe43484512568a0718b776049ea0b5f6f3e007520ebe206bf3f44eed8189c4e7bd98e965b2c4aae39200994ef6f4a094f51882958f9f01740614a7e624e6b679686e376a5d3f348a62b0688ffe4250a02c6be05247b7038fd41dfaa28f9202f1752500bc2ffbdd1df3462d7c21a7909ba090f4ce06d9c70a1544240692a2f36265bd34da3928e5185ba183ef8d9c18ca22a0c141573e904584b31e9ac45ebbddb46e4006176ed393a22071d94ea3255089daa00d3f247bdea5d45dd22966cb4772fc8430e602e3db2d9a37d541eb377240d0afa02cf9af56a3f0f2c30a0659ca905c906d4178707c5a4cb2530de9ac7613b0686aa0dd08fb62161b9771647a98cf8ff1c9e735c9c712795ef0c564f3be4a1498f6d8a0dbc26012bbaea11ce63400d6c319a517af82b4c1d7defc73e5f52d53ccfef201a0df21b134664d0a6d6c9320797d35b5ede85568c93ec594e9ab61ef9994c6f2a0a0c3ef633aec0a4a63d3bdf186a972995bf281c1211717741ae514bb914c5c6519a005c9248531c60761d86358914dc354b4edb87ea35ef526057f1a5897de4cd1cba078bc36f8dbc8db7245bb3290330dc81337a42418e6d82720e2883807b74d5803a09c78d063549ad17add128dd4324a98cd93b58bb70435b3e211ebfb9210db8422a02cdf2887c1c85af2961183ca34694903a5c85c93e38ef79b00859e3a6e81b42b80","0xf90211a0b923085dc78cf2ab0489315cfb0ebbe76c1d9b38bccaf3b5be06b48095aface5a0afc98f44a9e63637d188939b5e6ea342cf6fb042883ddd564f3fe657bb90756ea01c9e6091834f76a0f72731d982c522cbd9195f6f05001317ba88eaa7413f68fba01e5351421921b78a451f898dd7f89b7da2f6c0f29668dcba7bc46e49e1a4d254a039a8a2df8c0aa3b7f7e980004a04230787a28fbb6eca917382aa37390b4d7cf3a063686765435e064f4246b9ffbba262a9eb2708ea547db82b8efbfd2d65772018a01e8c5728b0ff9fb7e3f1b4cba5faa32c9067d34b2a35127ba2da501cd570c851a0bb226a1f610bfc3b58a814cd926c4a74140186b24d9e5a0ab775c072460ae068a0a1c27fd2ed0f15f75be505b80a8136b6fffbff3a9cc8a1cd681c9c79d9f644d1a06e66ffe0c914582a7ba628d74be61e6b5ffe99fe8b248105ce484a2d06725e41a09f95e9b8c6d8260b98c2f1acdb8d50c7d68a26d75152e00945e3b84ee90a3fbba08b8553a262a402651fa11765213bb63d4a2819ada913cad52b12c6ad697d9a46a0bc2d134e58c418102e3d7bbd1f4b834e0037408d0e668b3eba2f2a12f4bd78cfa0b38bebc75096c2d1d08d2012339976310d2c69984cabfd41c287e99345139455a071ea33dd5e9ed9f0afec7e86d70b3a250e1f5e9258a50ac6b62f6bf4774a18f1a074f3e83ce60fc75814f18e2c4a5f9e7433c6b1434402038c555751de249c153e80","0xf8b18080808080a0716dc2349a67d75533815556083f876fe23b5ed8fb49477ae77f75dfad0c5c2d80808080a0c328f972c8372d609366404f9868982546f23dc289fbcf66fbc070f654bca4af80a0205c16975897cf330ce42d27ef1cc74bd26748b176900f737cec5edb80ecd6e380a0a487e20e97ab9f735c3bcbd8b703208e0c8549224adbc1707eee2bd1c28b62a2a0f7932cafbe50458d0a254495af4624dea0e1091890145cf5ad9005be91f746e980","0xf69f32025a44ad6e63c5ca3b8679d5f154df97cc75bf475b0d4a226fcbf7a0b45995940b56ae81586d2728ceaf7c00a6020c5d63f02308"],"value":"0xb56ae81586d2728ceaf7c00a6020c5d63f02308"}]}}},"version":"2.1.0","currentBlock":2587057,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":192,"rpcTime":181,"rpcCount":2}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ },
+ "eth_getCode": {
+ b'https://in3-v2.slock.it/mainnet/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635b0fc9c31161008c578063b83f866311610066578063b83f86631461042c578063cf40882314610476578063e985e9c5146104f8578063f79fe53814610574576100cf565b80635b0fc9c3146103025780635ef2c7f014610350578063a22cb465146103dc576100cf565b80630178b8bf146100d457806302571be31461014257806306ab5923146101b057806314ab90381461021c57806316a25cbd1461025e5780631896f70a146102b4575b600080fd5b610100600480360360208110156100ea57600080fd5b81019080803590602001909291905050506105ba565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61016e6004803603602081101561015857600080fd5b810190808035906020019092919050505061068f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610206600480360360608110156101c657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610764565b6040518082815260200191505060405180910390f35b61025c6004803603604081101561023257600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610919565b005b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610aab565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b610300600480360360408110156102ca57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b80565b005b61034e6004803603604081101561031857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d42565b005b6103da600480360360a081101561036657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610eba565b005b61042a600480360360408110156103f257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610edc565b005b610434610fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f66004803603608081101561048c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050611003565b005b61055a6004803603604081101561050e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061101e565b604051808215151515815260200191505060405180910390f35b6105a06004803603602081101561058a57600080fd5b81019080803590602001909291905050506110b2565b604051808215151515815260200191505060405180910390f35b60006105c5826110b2565b61067e57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d602081101561066657600080fd5b8101908080519060200190929190505050905061068a565b61068782611120565b90505b919050565b600061069a826110b2565b61075357600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561071157600080fd5b505afa158015610725573d6000803e3d6000fd5b505050506040513d602081101561073b57600080fd5b8101908080519060200190929190505050905061075f565b61075c8261115f565b90505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806108615750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61086a57600080fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506108a781866111e2565b85877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610a145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610a1d57600080fd5b837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050565b6000610ab6826110b2565b610b6f57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166316a25cbd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b2d57600080fd5b505afa158015610b41573d6000803e3d6000fd5b505050506040513d6020811015610b5757600080fd5b81019080805190602001909291905050509050610b7b565b610b788261122f565b90505b919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c7b5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610c8457600080fd5b837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610e3d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610e4657600080fd5b610e5084846111e2565b837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610ec7868686610764565b9050610ed4818484611262565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61100d8484610d42565b611018848383611262565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111d85760009150506111dd565b809150505b919050565b6000819050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611220573090505b61122a8382611455565b505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611383578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611450578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a25b505050565b8060008084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea265627a7a72315820e307c1741e952c90d504ae303fa3fa1e5f6265200c65304d90abaa909d2dee4b64736f6c63430005100032","in3":{"proof":{"type":"accountProof","block":"0xf9020ba0af4f605dd0dbdbae5e92e0bf217576732da84ef7842bd136e616cffde755c87fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794a7b0536fb02c593b0dfd82bd65aacbdd19ae4777a0ac1a6897bdc4e187b4b7644ef27bc0145395ea80a7f466654e8e5ec689b807a9a06b1986936cc6bf1c32df76662cd4d14fa7e4193a2c4ebc3195176bc96d64990aa0249f0d1687352b1b8918eaba2ec96986f6865e8925a7da482122b4d9129175dcb90100c05282801800683249804000031a112ace8020105f10420822c341401c9584020009527c1c08241248000c04a20601143380060088000c090a1040e0902aad05490448019619e441c1805608088062064000a806a022b0008258100e2b422961244da6a00204038221820300083048180071500e28c400800c2020101100ea000521938024263020000106a096c901041014052c082010180010400a801010c28ec4010884100108260400801100894000814140b00200080021b02136080060801820032c001018ac7042852890005d1c03408b06a400a20111a834102122292010a40181a01408111c0800082a925fc28800042a230314008342048a81216e8707e79607e2b6898397b70783978a7c839761f3845ea4698c8a706f6f6c696e2e636f6da0ad4178a56524273f981025d6ca0f710fc85785b46257790b6c3f101a43b24c5f8837d2538c0053ec70","signatures":[{"blockHash":"0x760c642df13e6fc432e50f9312d5f570ffc8ccdb0c8174793e4c3c8612b80ce6","block":9942791,"r":"0x1b87c4c690c52d860c49598781ad7cffaef5d04dbd853a5b1d4a0efba1d0aca7","s":"0x6cb8b93dc4666db65d95c7acf4880adc6e55208f5176cabddf3dbf1da50abb6d","v":27,"msgHash":"0x4dc194e2bb5ca779b89b7ed6081c93e3e7ab1702c63f8e1a8bc17374b4112b22"},{"blockHash":"0x760c642df13e6fc432e50f9312d5f570ffc8ccdb0c8174793e4c3c8612b80ce6","block":9942791,"r":"0x4197ee2d64a7e142aa6bd40af3ae4b2365a36713aa2fd1443f7bc07ad50b8d22","s":"0x7b3fd4ea0d6eb47abc8d3e155dd73e91937fc40e67dd5feccc5992f7a91889c4","v":27,"msgHash":"0x4dc194e2bb5ca779b89b7ed6081c93e3e7ab1702c63f8e1a8bc17374b4112b22"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"accountProof":["0xf90211a0652d2ea07db9bdbaff91d6c16c8b9c4e925ac4413064aaf12b29610e8f8a36b7a0f443bb867526ca495afd5b2647e7174238171db90b6cfd51323f8229f4f575a8a0001e90518ab352a51fba6dab4434bb665f3f6c080e158e453ed6b602182907fda0a546ce65b6412b2ef1aee7cb9891bc7dc516cd05e738886efd3facf4b830c04ea05fae67b74a9ca95742fe5f11dbde9482fee6f64a84f4ff2b4c92ed883c9acd9ea068e9813b412cc705bcae06d90e413839edea0cc1ded353545f4de8c130b2ab17a0bc8f136623d6601e3093d833020c0d1c7f3be85cee11aea289ea0c9f8013109ea08032162ee77e564cb617051e33b3d15f92a56e2d38f2c70a696a85715f2d0a5ba0dc947549a0dfce68dbcf77f90a9784b2c60c7937c01a67c6fd5af9f074e8ebeca04a3e3a2411bb360060046431d9342a961ed2c25d42ad7cfa79c3572ac19fdd51a0da29c44a1457482ab9a6711d9fab67c7304b23e74adeef7a446fd431ffade2caa0bf0033e8347a916341480cacf9951f56cc7ba29fd7e56114003247e612227a2ba0cf360d54028c8d41fe315d2e05b41a8d63f78108103b4ce1ccf023a15833bd46a0d3b476f5d59e682a7f764c9062848c751e20e4c5febb9bc43a25ccee026c06b9a03b802604cd8c739ec29eb08a9484f57b94bb0f1c20461d2d187d96deed3aa683a0bf42c80cd86d9dfe7731dc0b9caa092610202c2b2b0502a31995ad4a1d96f32b80","0xf90211a0e3b77646faf55176ae69593ca9f6563455dd6c41f381d5787de0cb889f683ec3a052cd2eca79ff8140fb6162bfe84171698b9c14a423862803d9c6d24568416bb8a06e7666b88ef79c40e49d6a4c02e169a1148d8f401be53f06f8d6cab8c55c9203a01a947dc468abacd8b0599a6fc9dffc024368cf2416d96883409050639e1c269ea02b62b5deeb5157fc6f0f7b3e4d7ea006f3c99c374cdbb50a27ab0ce985cce9b9a031e57b264589b38c45228c42a1024af17a2283879e8d99364bebe2227d8fb9b5a02544a0b0c87e8252a7bfe20bac5c1527c7deb6525daf62cdbbdb1d79950a4c84a0718b977f4e6886de31b286e4b743f25e29f22174ac3f8974a876293b6396b2eea02e43de567360a37e8a0da95db4fd933b816a1b02e2fcdda234db550781669ed8a02449fe020fc431c640ea52ef85104f4cb7dc7e71ae37ab82cd9bcadd4999caf3a09b3ddd012d0fcb23e525f7c376543d6d457128d24b8fcd0add1fd3010c0e3715a08a2fa1b8a70e04be5b8fc800932c35356fc79fb6da00f8f360105a8743394e1aa0c4d1052107667557f5806ec6117d5dd7913b8e85f3c70f896b15c4a3653fe482a0e0d4075f7012cd2bc49c7af33b82e0933c4723e989825b42230b73c94ae4790da003c8121a12c671aed87e9492bab205e3023a35e9fba87f633c39198067ebac3ba0e75a8d23ad1f6902335cb74d2b757b26058ac5086c983c934f3a858b8484756880","0xf90211a0810cd57be8a5e34efc87ee5eb2168d999920380a51649882f8c7caea25562bfca0f664426f4c5a1ccfa9719ca29bfa05c03f7a525997dd136f3af2954782606ac8a0ab402b1e7ea4a9e7e62d8a8d3060cc2547ee66787146ed7def3c421aee95b616a002f1a56b4e9af014e195829db4cef65e66ad424f151ef2421678b32fae11ff89a0d65c1462b1152bdb007c78e9a2c52d18ae83a39ed4061cae2d47e720dd70cf53a0970aaf49f28b56d9b802f0d63df6d4007baf073acddc667778628c7c16948891a0725b85ee9add9881887d0b4e340071f352587b00f928c823ae5cdaac47735bb3a072908ea403367671bf6f104ad0bd9c40eb46585fdc85219e91e079145381b4fca099e95b815f7a4c6a4efe4ae68c531f75dd81b3cdfbe8fd075d888db0c79ab31fa0801de6e5fc3d2f76983ed5505a09324653e6b0a57e036c9ffc2b0bcdb07025daa06afd2d8715bab5ae6eae53383ba454cc3de5388d12355bd35da0ae2c6719d8cea0d37195f4144ab52383aa31050d17fa56aad9c65a8f271beaee7431775339400fa0f17ef06005d38d71561f5734d57a23dee528872ac18097a66cf74585e86d2b28a0501b4f305c95fdf60092e803d2474d8d9a21bf15d54ffae27ba3bf46691c4d8da0a1e078a81a7898e1f7821ed3fe9de9c1b66dd83d1d925d2fda28e13df49a1c2fa0ae19f63667eb3f1a3b18b5374851b83384380c67f3b4a077fb92f0ae8137db1580","0xf90211a0d35e84e98c291d53cede851d5cc1476020d0f8564f701b55347abb52476ea93fa04e5ba085a3dce5b88b541ee6c13aeb847829f3e1b169c8535115511f0c316ec5a03aec623f708e524d3acf46e242abc4fcf1178f275b437e0fa015807ecc9c5b23a02073f5b973742a2dedf7aaf0c32fbef0931d683aa2a135361001202ea731f17aa0f257514ae0ce8e1a8f74001ed6d3ab7486f92b487d8eff310c30487350efeddda09a735225b39600cf7ee84ce7590a911b8674afd680b07961bc785bf317ad7b58a0bef6d6bbce1dd0bef5dab0c34261b66e358b4418e349623908699f4853660679a0213fd8a18a6a284259f5869be460e515c258395fcdfb1ee764aae2b4b5ba4723a0a6399bf4739df0b52404716e4b8cda306756855faac2a27fecbc7c10d104e447a0c2682c5a7a9a5e5ce87b101f37f3fca2a17188954c748d392160b2f15d04784fa0fc3c45f323e54d49e3c8da7e95be0186b740167f200388347f73689c6ef698f5a020e7ff1b310aa981b1d4cdf65e7781b683c974d89f282002864b59911a707e50a0cc02e0878f531040c339aba365d19ea09df47a352cf85f3adff175931f9a456aa02c2575a16d3508e6d2b8b060f119f7e3692caa0126a833c02d706726cea4a1aca0004163971a81fd213e90c958c101bff2c43dd85e587f626da9af9220b5492e22a0cc9bddc182a6972ad5bfde042f671fb3316eeb8e4586667260ae02eea5fc62a180","0xf90211a0caddbda2744ef6ca7ce78c8c42b1cf8e64361393ee44a3bae750fc8ab0feb5aca03f90fd9f328c8816d0fd15e4cc664ccfe10d5e2d331fdd745e64b2831990aaf0a0f0fbeb415948a5eb5704a6a298e6e8968efdbcbb4e6079c165dec1eb957ef0c7a00270c12baa3d18ed0efcbc036ab9a1b0b0f221b440598eb6f487aa32697c42f4a0ed449fb6298dd42c0d0988b42d2fc5c74d6b5d5cff4dca421d62ece60f554246a0e2e1b6d2a953f25bb783d105a42c9a6be19d07c7d19f71aa7f874f405a17d835a028c7112ff63d318c5c502b25ae2218e7503ee0f26aaca0a0a74500b85cc8b79aa0c6a5601599a9df66ac619ca9c11ed50da23903ca49e3763e8b37d767c4f57753a02173d1d1e2a98fe0e36a400c4809de35ec5cdeadf595dd18041f9a4561edced5a0a5ba811eed0b833f844988be3a21ac9756b61604f4157d64a26154dcfc1762dfa07c6df0351396276de731b2d46f2887234965cd6ef22e2beda956a58db84eef87a07d63fd72e40deae98cb5f7ae6cd5ed76459a9f3dcb53942f7743652743724c22a082293e94cb57aa391fb0a8a27f50fdc060272dfe054b0bf1fe5eed6821153793a0af0acc5af3e00748d0362cbb74100755e8dfcac7a45b1ea8185c384b7775b5fda0d6c810de8f7852ad3f85d25906ba106f57f0489a69cd403291c43169dd09bd7da0c2288d5e0b8834de1981563504867d94dbd32cc6f53dbe4bfda6facc6b3f45d580","0xf90211a03dc2949012be86f067afebe897c0ccd283ef5f1912710da9913c55ba3f795454a081bea4c6bd2e2026b5c6fdfa418b75662c7122d675f9a5b6415aaec3e2eb2a8ca05cd984d28bd67177736162fb80ba38d573cf5842e9a0f21881dd6b124ed22f3da0962c9bb5b52bb46492f6b43f76289c21c5dfb59983b4d4a9e26eef61f94e5b1fa0d5b2ab48bbd5d004d42b08d8fcb6d667b66e4764089b37ab5944bb1902218a46a0adf96f10cbd0242f4af39f240a5b52abf08311ce3014898e5359be8673fd0edea0522f2f81c49a9dde3af7c8f38facd88b99554bf9b3ca2cf7e3c159a1eaa0a4a5a0bbfb6bf77930ed25fb7123f8ac805ce42920746b6f4d6d9da85dc7479d6c50bba058ec4301ebc80d959f9eec90ef954bdabdf55975bbb5943a5ddaaa2ee3123549a04a85a0e52bc9da1ecd09e70cbb7baa759de8c7fc341f0b2ed68c1be5bc2821b1a009bb4288bdfb67f073711492801a2f9c4d719967eaea129a6de62b2d2e599d67a0a196adab721d52fb7c5b938e87692d1feed67ff9be6fd050f7a780a5ff08d96da09deeb4d161ba8dc2ff9d7098bd76ecfd548c52df13a1dafe39f7666c5e277cf1a0e53f585dd536d7f610a41dbba97b023e0660f0ab62c1eb009b273eeea98677eea0fefb9489bc053a8878a80aa198cebecbdc7e8c5f9dc7cd82c6a920cba96bdbe8a0f2ea87d62a695bc3c4936b9f503f9684334c044246acd1459105c3cf7d3b6bc080","0xf8718080808080808080a04a88e4063326e9f1c0149653f8da9056a293687e939d79212d94e4bc2b87260d80a04297cf3bb9d774bb05365c184d52ec92115082a2b613518e586cadef7c52a4c480a038f2d92dccabf6ce5c35dba688eb72cc275146b395f9b880d103748b215e00a680808080","0xf8669d3a53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0fa772a28a73cdac41da83968ab3663b9ae080e30c0d2728477640cf9a9726e48a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xfa772a28a73cdac41da83968ab3663b9ae080e30c0d2728477640cf9a9726e48","storageProof":[]}}},"version":"2.1.0","currentBlock":9942797,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":451,"rpcTime":350,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/mainnet/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635b0fc9c31161008c578063b83f866311610066578063b83f86631461042c578063cf40882314610476578063e985e9c5146104f8578063f79fe53814610574576100cf565b80635b0fc9c3146103025780635ef2c7f014610350578063a22cb465146103dc576100cf565b80630178b8bf146100d457806302571be31461014257806306ab5923146101b057806314ab90381461021c57806316a25cbd1461025e5780631896f70a146102b4575b600080fd5b610100600480360360208110156100ea57600080fd5b81019080803590602001909291905050506105ba565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61016e6004803603602081101561015857600080fd5b810190808035906020019092919050505061068f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610206600480360360608110156101c657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610764565b6040518082815260200191505060405180910390f35b61025c6004803603604081101561023257600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610919565b005b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610aab565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b610300600480360360408110156102ca57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b80565b005b61034e6004803603604081101561031857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d42565b005b6103da600480360360a081101561036657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610eba565b005b61042a600480360360408110156103f257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610edc565b005b610434610fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f66004803603608081101561048c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050611003565b005b61055a6004803603604081101561050e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061101e565b604051808215151515815260200191505060405180910390f35b6105a06004803603602081101561058a57600080fd5b81019080803590602001909291905050506110b2565b604051808215151515815260200191505060405180910390f35b60006105c5826110b2565b61067e57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d602081101561066657600080fd5b8101908080519060200190929190505050905061068a565b61068782611120565b90505b919050565b600061069a826110b2565b61075357600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561071157600080fd5b505afa158015610725573d6000803e3d6000fd5b505050506040513d602081101561073b57600080fd5b8101908080519060200190929190505050905061075f565b61075c8261115f565b90505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806108615750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61086a57600080fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506108a781866111e2565b85877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610a145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610a1d57600080fd5b837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050565b6000610ab6826110b2565b610b6f57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166316a25cbd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b2d57600080fd5b505afa158015610b41573d6000803e3d6000fd5b505050506040513d6020811015610b5757600080fd5b81019080805190602001909291905050509050610b7b565b610b788261122f565b90505b919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c7b5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610c8457600080fd5b837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610e3d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610e4657600080fd5b610e5084846111e2565b837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610ec7868686610764565b9050610ed4818484611262565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61100d8484610d42565b611018848383611262565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111d85760009150506111dd565b809150505b919050565b6000819050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611220573090505b61122a8382611455565b505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611383578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611450578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a25b505050565b8060008084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea265627a7a72315820e307c1741e952c90d504ae303fa3fa1e5f6265200c65304d90abaa909d2dee4b64736f6c63430005100032","in3":{"proof":{"type":"accountProof","block":"0xf9021ea0760c642df13e6fc432e50f9312d5f570ffc8ccdb0c8174793e4c3c8612b80ce6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400192fb10df37c9fb26829eb2cc623cd1bf599e8a013eae77ab1dc304a5aa65c727344d4848da85c1ac294327d8889e95210a0efcea0f9ae0debaf540da3ce81941f7df29eed7c07feb8a1baa87c76227933cbf050f3a0cc5e48c1d1cc5eb76e5777b7d4526e532037c3c6e00d102c609effa4b5e12b6eb901008002000000d22418098023000008100040040000000060080200813000080100000400540000084000000000004c410280400420400020810040c00000822000400084008841841048029088008240000040200401200100800210040000004061281025020100040000000000800800000010000800020000002150100010000024a000102024968000002898040014202ac02c098201004842001000900000408800000140a000820002904100000000004620a000000000448000180000000008000302000000901010001420000c0140404004880044402100201844200040000001000800008000008500100024204000200000000062430004009040008707e892faa3b35f8397b70883979d5f8325fbfc845ea469929d505059452f457468657265756d50504c4e532f326d696e6572735f4555a0500b6110488f949f95fce063a552212c3195e300bf4f993a8cae4593670bc26c8811c12010049b55a8","signatures":[{"blockHash":"0x9acacc7f5bcd4656c42e649f54e2bae9657be4210cea3f55aba17d1bd55da917","block":9942792,"r":"0xb97a8bf67b11aab978ed3389638b47072842532ef3e01623052079f3a1c8fd6e","s":"0x0ad0ef3dacd6b66f46c0e643b745d83f01264f0b374c23cd98b9fb43f0bc7dfd","v":27,"msgHash":"0xb3fb3d512ff491848184f6fb7c3200609f2c5ebfb3f05d296e59886649cde73b"},{"blockHash":"0x9acacc7f5bcd4656c42e649f54e2bae9657be4210cea3f55aba17d1bd55da917","block":9942792,"r":"0x1905bc722af10f482a7ee927d528e14e31ab1bfb121e0f57859a65f83d1caee3","s":"0x1d08f9f04c1530e186dd73c250723ef6b2498e8c399e9eb069f1dcc7ea0edaa3","v":27,"msgHash":"0xb3fb3d512ff491848184f6fb7c3200609f2c5ebfb3f05d296e59886649cde73b"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","accountProof":["0xf90211a068197f8a5ac72372455fc0a987fc75cc1a7210c86c06ec3755e121d90aaf4b87a0879a37063ddb28c5f0292ea62024fb5ee950d6bf74356b7d8020d38484a7d29ca09c5459401eae22a00dd19e032cd53f62cb74d2a7790d4d3eee121cc133582e71a0d9545c44feb553050184989efb7d601a1123b301fd1eb4fbe39e2af0b5b92849a02b9623860376b10aaf499dcdbce93f148eaeeb8ec13edd8272f9eb1383e03865a0febf206d265fe3bfbcff4c97fed9f3b893a39ff42991d3cf4a06745e2fccefc6a0069f456058f0be17eb727352dc845cdca6f54ac864efe5178fb97198e4f94befa08649ada2a5a1f249e1e6e145e90a4c9517278022d0823da6e7592b201ac1fce5a0720a9be8f0684fb6077b1476c3b4aa37ee5cae95df1c096802b8d8ce0c65717fa01f6d3796318207564c7d471c3fd172fae3101d87e3155ca6e54c97743ec9473aa07dece8c6e77992b0bae60424d6654114136666649a3c3eadecfa5eaf71b2cc78a09d661337b73d97679d088a233d3386e4ac4ef985df2defe022795eb30d83cf65a04229d743b63be14a7e9ee0dd5b1b74d18f2210276d17d13ae1c670acd2574359a0a0f90642eebecc5d39de66c31fd1dbee0d4d77d96724f0ed244311c57d927109a08f3d94ec8a61cce6a62f09a6f3b46c79f6d9cf183771757f2452878d83bd9ec2a062e12a94353b5aff2bad5aa45b4c9f0955461ddea20896dc8082663daa0aa2ec80","0xf90211a0e3b77646faf55176ae69593ca9f6563455dd6c41f381d5787de0cb889f683ec3a052cd2eca79ff8140fb6162bfe84171698b9c14a423862803d9c6d24568416bb8a06e7666b88ef79c40e49d6a4c02e169a1148d8f401be53f06f8d6cab8c55c9203a01a947dc468abacd8b0599a6fc9dffc024368cf2416d96883409050639e1c269ea02b62b5deeb5157fc6f0f7b3e4d7ea006f3c99c374cdbb50a27ab0ce985cce9b9a031e57b264589b38c45228c42a1024af17a2283879e8d99364bebe2227d8fb9b5a0707183a61ad09b765bf5678b6494559e730489e762f33e9ef571d06da1e7783aa0718b977f4e6886de31b286e4b743f25e29f22174ac3f8974a876293b6396b2eea0157b245ba20a04bc6cbb974c702408f1f36065e090844829c2f898e74709d405a08dd6e660d76bb6e44dcfdb65c21fdc5529d3e659ce4a4482d4d540b4d0dc85e7a0d446b7383afcd0187adc8624c21dbcc5c10a7933748351b63cc1a57cef5538c8a01c47f319dfc1d4897b5b4425247b68af4a28647dc5101766a512e35d12cb7c87a0c4d1052107667557f5806ec6117d5dd7913b8e85f3c70f896b15c4a3653fe482a0e0d4075f7012cd2bc49c7af33b82e0933c4723e989825b42230b73c94ae4790da003c8121a12c671aed87e9492bab205e3023a35e9fba87f633c39198067ebac3ba00ebe1696b6e749ad7db5696267bd59a11c581cbe075af3185ff543c80fd4883680","0xf90211a0810cd57be8a5e34efc87ee5eb2168d999920380a51649882f8c7caea25562bfca0f664426f4c5a1ccfa9719ca29bfa05c03f7a525997dd136f3af2954782606ac8a0ab402b1e7ea4a9e7e62d8a8d3060cc2547ee66787146ed7def3c421aee95b616a002f1a56b4e9af014e195829db4cef65e66ad424f151ef2421678b32fae11ff89a0d65c1462b1152bdb007c78e9a2c52d18ae83a39ed4061cae2d47e720dd70cf53a0970aaf49f28b56d9b802f0d63df6d4007baf073acddc667778628c7c16948891a0725b85ee9add9881887d0b4e340071f352587b00f928c823ae5cdaac47735bb3a072908ea403367671bf6f104ad0bd9c40eb46585fdc85219e91e079145381b4fca099e95b815f7a4c6a4efe4ae68c531f75dd81b3cdfbe8fd075d888db0c79ab31fa0801de6e5fc3d2f76983ed5505a09324653e6b0a57e036c9ffc2b0bcdb07025daa06afd2d8715bab5ae6eae53383ba454cc3de5388d12355bd35da0ae2c6719d8cea0d37195f4144ab52383aa31050d17fa56aad9c65a8f271beaee7431775339400fa0f17ef06005d38d71561f5734d57a23dee528872ac18097a66cf74585e86d2b28a0501b4f305c95fdf60092e803d2474d8d9a21bf15d54ffae27ba3bf46691c4d8da0a1e078a81a7898e1f7821ed3fe9de9c1b66dd83d1d925d2fda28e13df49a1c2fa0ae19f63667eb3f1a3b18b5374851b83384380c67f3b4a077fb92f0ae8137db1580","0xf90211a0d35e84e98c291d53cede851d5cc1476020d0f8564f701b55347abb52476ea93fa04e5ba085a3dce5b88b541ee6c13aeb847829f3e1b169c8535115511f0c316ec5a03aec623f708e524d3acf46e242abc4fcf1178f275b437e0fa015807ecc9c5b23a02073f5b973742a2dedf7aaf0c32fbef0931d683aa2a135361001202ea731f17aa0f257514ae0ce8e1a8f74001ed6d3ab7486f92b487d8eff310c30487350efeddda09a735225b39600cf7ee84ce7590a911b8674afd680b07961bc785bf317ad7b58a0bef6d6bbce1dd0bef5dab0c34261b66e358b4418e349623908699f4853660679a0213fd8a18a6a284259f5869be460e515c258395fcdfb1ee764aae2b4b5ba4723a0a6399bf4739df0b52404716e4b8cda306756855faac2a27fecbc7c10d104e447a0c2682c5a7a9a5e5ce87b101f37f3fca2a17188954c748d392160b2f15d04784fa0fc3c45f323e54d49e3c8da7e95be0186b740167f200388347f73689c6ef698f5a020e7ff1b310aa981b1d4cdf65e7781b683c974d89f282002864b59911a707e50a0cc02e0878f531040c339aba365d19ea09df47a352cf85f3adff175931f9a456aa02c2575a16d3508e6d2b8b060f119f7e3692caa0126a833c02d706726cea4a1aca0004163971a81fd213e90c958c101bff2c43dd85e587f626da9af9220b5492e22a0cc9bddc182a6972ad5bfde042f671fb3316eeb8e4586667260ae02eea5fc62a180","0xf90211a0caddbda2744ef6ca7ce78c8c42b1cf8e64361393ee44a3bae750fc8ab0feb5aca03f90fd9f328c8816d0fd15e4cc664ccfe10d5e2d331fdd745e64b2831990aaf0a0f0fbeb415948a5eb5704a6a298e6e8968efdbcbb4e6079c165dec1eb957ef0c7a00270c12baa3d18ed0efcbc036ab9a1b0b0f221b440598eb6f487aa32697c42f4a0ed449fb6298dd42c0d0988b42d2fc5c74d6b5d5cff4dca421d62ece60f554246a0e2e1b6d2a953f25bb783d105a42c9a6be19d07c7d19f71aa7f874f405a17d835a028c7112ff63d318c5c502b25ae2218e7503ee0f26aaca0a0a74500b85cc8b79aa0c6a5601599a9df66ac619ca9c11ed50da23903ca49e3763e8b37d767c4f57753a02173d1d1e2a98fe0e36a400c4809de35ec5cdeadf595dd18041f9a4561edced5a0a5ba811eed0b833f844988be3a21ac9756b61604f4157d64a26154dcfc1762dfa07c6df0351396276de731b2d46f2887234965cd6ef22e2beda956a58db84eef87a07d63fd72e40deae98cb5f7ae6cd5ed76459a9f3dcb53942f7743652743724c22a082293e94cb57aa391fb0a8a27f50fdc060272dfe054b0bf1fe5eed6821153793a0af0acc5af3e00748d0362cbb74100755e8dfcac7a45b1ea8185c384b7775b5fda0d6c810de8f7852ad3f85d25906ba106f57f0489a69cd403291c43169dd09bd7da0c2288d5e0b8834de1981563504867d94dbd32cc6f53dbe4bfda6facc6b3f45d580","0xf90211a03dc2949012be86f067afebe897c0ccd283ef5f1912710da9913c55ba3f795454a081bea4c6bd2e2026b5c6fdfa418b75662c7122d675f9a5b6415aaec3e2eb2a8ca05cd984d28bd67177736162fb80ba38d573cf5842e9a0f21881dd6b124ed22f3da0962c9bb5b52bb46492f6b43f76289c21c5dfb59983b4d4a9e26eef61f94e5b1fa0d5b2ab48bbd5d004d42b08d8fcb6d667b66e4764089b37ab5944bb1902218a46a0adf96f10cbd0242f4af39f240a5b52abf08311ce3014898e5359be8673fd0edea0522f2f81c49a9dde3af7c8f38facd88b99554bf9b3ca2cf7e3c159a1eaa0a4a5a0bbfb6bf77930ed25fb7123f8ac805ce42920746b6f4d6d9da85dc7479d6c50bba058ec4301ebc80d959f9eec90ef954bdabdf55975bbb5943a5ddaaa2ee3123549a04a85a0e52bc9da1ecd09e70cbb7baa759de8c7fc341f0b2ed68c1be5bc2821b1a009bb4288bdfb67f073711492801a2f9c4d719967eaea129a6de62b2d2e599d67a0a196adab721d52fb7c5b938e87692d1feed67ff9be6fd050f7a780a5ff08d96da09deeb4d161ba8dc2ff9d7098bd76ecfd548c52df13a1dafe39f7666c5e277cf1a0e53f585dd536d7f610a41dbba97b023e0660f0ab62c1eb009b273eeea98677eea0fefb9489bc053a8878a80aa198cebecbdc7e8c5f9dc7cd82c6a920cba96bdbe8a0f2ea87d62a695bc3c4936b9f503f9684334c044246acd1459105c3cf7d3b6bc080","0xf8718080808080808080a04a88e4063326e9f1c0149653f8da9056a293687e939d79212d94e4bc2b87260d80a04297cf3bb9d774bb05365c184d52ec92115082a2b613518e586cadef7c52a4c480a038f2d92dccabf6ce5c35dba688eb72cc275146b395f9b880d103748b215e00a680808080","0xf8669d3a53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0fa772a28a73cdac41da83968ab3663b9ae080e30c0d2728477640cf9a9726e48a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xfa772a28a73cdac41da83968ab3663b9ae080e30c0d2728477640cf9a9726e48","storageProof":[]}}},"version":"2.1.0","currentBlock":9942798,"lastValidatorChange":0,"lastNodeList":9942625,"execTime":152,"rpcTime":75,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-1': b'[{"id":1,"jsonrpc":"2.0","result":"0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635b0fc9c31161008c578063b83f866311610066578063b83f86631461042c578063cf40882314610476578063e985e9c5146104f8578063f79fe53814610574576100cf565b80635b0fc9c3146103025780635ef2c7f014610350578063a22cb465146103dc576100cf565b80630178b8bf146100d457806302571be31461014257806306ab5923146101b057806314ab90381461021c57806316a25cbd1461025e5780631896f70a146102b4575b600080fd5b610100600480360360208110156100ea57600080fd5b81019080803590602001909291905050506105ba565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61016e6004803603602081101561015857600080fd5b810190808035906020019092919050505061068f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610206600480360360608110156101c657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610764565b6040518082815260200191505060405180910390f35b61025c6004803603604081101561023257600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610919565b005b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610aab565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b610300600480360360408110156102ca57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b80565b005b61034e6004803603604081101561031857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d42565b005b6103da600480360360a081101561036657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610eba565b005b61042a600480360360408110156103f257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610edc565b005b610434610fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f66004803603608081101561048c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050611003565b005b61055a6004803603604081101561050e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061101e565b604051808215151515815260200191505060405180910390f35b6105a06004803603602081101561058a57600080fd5b81019080803590602001909291905050506110b2565b604051808215151515815260200191505060405180910390f35b60006105c5826110b2565b61067e57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d602081101561066657600080fd5b8101908080519060200190929190505050905061068a565b61068782611120565b90505b919050565b600061069a826110b2565b61075357600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561071157600080fd5b505afa158015610725573d6000803e3d6000fd5b505050506040513d602081101561073b57600080fd5b8101908080519060200190929190505050905061075f565b61075c8261115f565b90505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806108615750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61086a57600080fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506108a781866111e2565b85877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610a145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610a1d57600080fd5b837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050565b6000610ab6826110b2565b610b6f57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166316a25cbd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b2d57600080fd5b505afa158015610b41573d6000803e3d6000fd5b505050506040513d6020811015610b5757600080fd5b81019080805190602001909291905050509050610b7b565b610b788261122f565b90505b919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c7b5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610c8457600080fd5b837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610e3d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610e4657600080fd5b610e5084846111e2565b837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610ec7868686610764565b9050610ed4818484611262565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61100d8484610d42565b611018848383611262565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111d85760009150506111dd565b809150505b919050565b6000819050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611220573090505b61122a8382611455565b505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611383578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611450578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a25b505050565b8060008084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea265627a7a72315820e307c1741e952c90d504ae303fa3fa1e5f6265200c65304d90abaa909d2dee4b64736f6c63430005100032","in3":{"proof":{"type":"accountProof","block":"0xf9025ca01aebaffc170ddd38cfea474371dfc56a1fdd494711c02220d74ea4a0854f3472a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a06ef90ef4b638b35751749168332059e4464df4110ab5c45c82caecafbe3a9caaa0005323b4f30d524e88c0dbc081e639b1acc466e834437cf2a56232590a13c9b0a01c2c5023ff2c2fd451d4ad090126a9180619c3d13d26adb9bcd4cf6bd057ca78b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000400000080000000000101000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000100000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000800020000000000000000000000000000100000002000000000000000000000100000000000000000000000000000000000000000000200000000c000000001832779bc837a12008301b1be845ea47dacb861000000000000000000000000000000000000000000000000000000000000000059d0bda92a11815c0db4d7116322f96b002b657e1da1b02bb086d3fa6945c70a2b40d0fc8a8279330e56540562c9e749baae585c1d21dc97e0d39cae7e4fc8dd01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0x0a54b8e9d1ffc503a90d679e850e689d114ee65dbda6bd256bfa0a0c74a02710","block":2587068,"r":"0xeb5e8d98da0de93f484af7f82c3c491831238615c4f063a5f3acabf9eec40622","s":"0x3be2df10043b74f2318ef73fd94c906d41800237c0ccaa559f4013fedebd5f17","v":27,"msgHash":"0x12f0a52e9e78b23426bfb624e57662902583842ce915d6c98b8b5d71dd1f74b3"},{"blockHash":"0x0a54b8e9d1ffc503a90d679e850e689d114ee65dbda6bd256bfa0a0c74a02710","block":2587068,"r":"0xc84a4da9e908a21c20e7cd527e8ebfb53cca238acb914325a43adf0a602d75d1","s":"0x39407f857a86ca28b2f25a6dea3a4faf4a86fec8cd1ce6dc630017e79a79af0a","v":28,"msgHash":"0x12f0a52e9e78b23426bfb624e57662902583842ce915d6c98b8b5d71dd1f74b3"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"accountProof":["0xf90211a06e3884346d957ebec001e3e8e5004ca1d679d798cc7b10d615d2152e8def48e3a09819676032e879bf9838b85f8f178818bd35e586669672ae937c39cc8aa4493ca0f8f1d8c4d2200a29d919ad79cf76a18a1659b1b9e27cab29262aead09657477aa09693ae7071af1e5a92b5184b8318f4f6b0cb18329007c40e1bec14de2227efc1a0158d3d140de9be8def09f4e69eae0ed3d6c3091c39f8265a10254f8425c164f9a00f067baab004d0994abe913676072f0098c8fe374b644dd02bbf129e9e993724a016bb47179bb030e32abb0cd3367df83ae46f06fbcba9fd04c860bb5f3b12d0f0a0ff8ab35fc5c34ac9fea1ef8657345f78ed296096805427c780012133eefefed9a0d67e2aedef33f705451de8c65410878036aac40429f3ee9fd35f58d959fe19d9a03acac961d509e99bd30b4036c042e1f9f5483de204902809cb428351e6725721a0a7f4dda9e198b90382319b4f0d4b1bfc2f04c8eaa13e2202fdbd48ca56b3000ea0c4ca4b061cb1588d0d6036bfc4a6fbc1de5a9f6d2da5701286da1c35864d49f1a060c5648dccc343d208d0b78f179993b0573caa12d805dd6cbdb3c4e6eee1b44ea0b0c940263c2150bd867850bed2170330c039145bab8d6ba200ca510d792e752ea0463c973251547d2805cfa4802a579579416276e3def59493c76d4f924aa15efca0d09280ad32d2053201bfe890df1d04bb18b39da8d072c11bb7c7a7ef578f919a80","0xf90211a0eccd829d32a260dbd58b39d0ad4fc865fdc2b4fed7e58426318c622ebaa5f02fa07f47fd520453962d0c5673b26c73c21fab0127ddccb0c623a8feabe197ed443da0e4d88df720993b5214761217a6f692636a175cd68afdbdb28810f58b1a6fb0e8a0b50b79fa9186646ca175a7ab32f4103d1273b5fd4e1e455020a5ab9e27541d9fa0ba0fb4c575c2263c7f5bc12d2dc32566f0f45c2907c2452160a6243d98c5e359a0c7c9ee54e08d27465cd96c438ba06c1bdd41f8c4c1c535d3cab1013372995b8ca045184cd142f6b4e085ba7a12f497392988858793e097e62dd8006b62cc2d40e0a0ff22b9b95164fe30e6feb1ff30acf5479949023d94aa84757c5509cc72f14611a04af1b78f7369cb80d294b816ef4150dac587e74b5e4fd1d694ccdc70f7b8dae9a0927c123f2b85b1cc36dadc9a7480bbb0f340f55106a7a191bebb4c02a80eebfda071f77ee6ae59898098022b01af4e9a0629635cd988e513ccd5f0f85ae7af81a8a0d431d1895f12cf91a594383bfb97743e34f0ad2f0f40269e7183ad8a8e3862dba0c2a3691c28c0547264a4d39ee81c4ce8e7826f2013e5b20a2d74d2efd935a44ea08deecacce3e0145aa8590ac58333cd5789024e4bd0cd927853f6198885a82d2ea0022f54fd50be1b7133344374032c146a276d5e68f1c1e9279f04c8c7f9e69120a0d37b2c683614801ddf9a63ef70eab7035afae663229d94e28c428ec6acb9be0880","0xf90211a0ce97293c34549170171bb723390dd47dc53b8237186c1dab1e8c578f181da75ba022c74c0c055f141c9ab5e43754f8dcd806bf80ae7f9280ed841880ba88f41f95a032105d2b5c182771994280ab031f650a6a8cdff20949d04cccad7b46130f913ba0d0f1612ff9f1d9436340ad0d65f68fb5f6df1e2faa764c12af5a9ad96d62761da0b4e8682ab002a59733edf9d308315f88797c6b87c24c9bbba8c56822533d19c9a02f2a237d03b62784f82c9c18405494ed771ea12fcac9b1329e9830ba3ae8d710a029aeee66e4afd9f9bf4433a02ccbb7b2f56d5e8745d0d63c40d5c23dfe75de4ba0d0211b072f1382dac5de0b3d6fcf2b6b52ecdb3cf72d798c09058665c361940fa03f8df8c9f0a9770e8fdeb3d162e2b74d38f2cc8de3e7f776d7a5b24c0408d25da06f1b88bce40ab519418a821f918d9b8006dc165b13e1551209756bd35ea1867fa01796b1002df593ef8c02a9c4b7b07b7003710512f31a964e0c5de0339f95061fa0e70a10f60c513e3ea2ed418df7fd1c70e6a74971edf6cc65cce9dd5217c5766ca067f3b37f5f1ba9862694b0707203e5ae79e3bca5c5b6194ddfbdcae38096d736a0e03870853881d3fec38abc662478cedbe84669b510433b073fa902e99985f586a05a30f44daa3205e3c7ef8a4a42517bc72f7a09757fdd534dac361bef3f7b38ffa09e46a57cab556b233914adb7ed2057cefc8c92e8d9257cf917be5d18ec57052180","0xf90191a090180abf51ee9a8d06b322766f3cf17aade5f5606d54fc17844f062a105e4aab80a09fd4239f754ce994e3f05c29b0800c8fa29ea7476f3d1bb33afcc3b33029b04ea0c32c2ce9a42b69f26eb54ccf4f397f9fa5c64b1289972e00f5df914f3b867d8ea0339ffbbc8b267ba43b478c855cf7c3b65b5681198dbe14a6c383d6e927fb99f1a075f2e6febe371c57c91644ef405b342b831264580cf994fd94c7d42ae554ae9aa0c95784b61cd7b153e42c8e22d91028bcd9b7a440e8bed87d5f54cbfea185b05a80a0918bbbebb389e4c100248c7d1ce4df01aeca2e2214cb89f4c3050d73efdbc28c80a0d8dff14cd8d20fe86f1abcc1d12cc7004b5d82af5fa65b16c6593d6ae3e35d76a04b75c24381c9c971ab560c96baf1e65128510c2a7c71e73b7c4533424eb376d3a02933b22375eaa4148e5cf2f687209eb60f9fc3c93af79e7d09bb7a483e5c922380a07caa3f3785c08bc622dbd2b81f4437c95467a9f137a0e83ece5c5c236cbc03caa0e1f6bc975a6f522766aee88f41212e45ff4519a197cd665fba9421b0242d8bcf80","0xf851808080a0b11c6b2f2d89847435e8696888779533b8556adb7a26799a95a4fe4396868de8808080808080a004765232d3d7c62b886a9855d8074b75a2b597b4dd7ad2e964ed0a0642cb1266808080808080","0xf8679e32ca53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0a36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xa36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69","storageProof":[]}}},"version":"2.1.0","currentBlock":2587074,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":611,"rpcTime":209,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/goerli/nd-2': b'[{"id":1,"jsonrpc":"2.0","result":"0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635b0fc9c31161008c578063b83f866311610066578063b83f86631461042c578063cf40882314610476578063e985e9c5146104f8578063f79fe53814610574576100cf565b80635b0fc9c3146103025780635ef2c7f014610350578063a22cb465146103dc576100cf565b80630178b8bf146100d457806302571be31461014257806306ab5923146101b057806314ab90381461021c57806316a25cbd1461025e5780631896f70a146102b4575b600080fd5b610100600480360360208110156100ea57600080fd5b81019080803590602001909291905050506105ba565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61016e6004803603602081101561015857600080fd5b810190808035906020019092919050505061068f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610206600480360360608110156101c657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610764565b6040518082815260200191505060405180910390f35b61025c6004803603604081101561023257600080fd5b8101908080359060200190929190803567ffffffffffffffff169060200190929190505050610919565b005b61028a6004803603602081101561027457600080fd5b8101908080359060200190929190505050610aab565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b610300600480360360408110156102ca57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b80565b005b61034e6004803603604081101561031857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d42565b005b6103da600480360360a081101561036657600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050610eba565b005b61042a600480360360408110156103f257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610edc565b005b610434610fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104f66004803603608081101561048c57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803567ffffffffffffffff169060200190929190505050611003565b005b61055a6004803603604081101561050e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061101e565b604051808215151515815260200191505060405180910390f35b6105a06004803603602081101561058a57600080fd5b81019080803590602001909291905050506110b2565b604051808215151515815260200191505060405180910390f35b60006105c5826110b2565b61067e57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630178b8bf836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561063c57600080fd5b505afa158015610650573d6000803e3d6000fd5b505050506040513d602081101561066657600080fd5b8101908080519060200190929190505050905061068a565b61068782611120565b90505b919050565b600061069a826110b2565b61075357600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166302571be3836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561071157600080fd5b505afa158015610725573d6000803e3d6000fd5b505050506040513d602081101561073b57600080fd5b8101908080519060200190929190505050905061075f565b61075c8261115f565b90505b919050565b600083600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806108615750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b61086a57600080fd5b6000868660405160200180838152602001828152602001925050506040516020818303038152906040528051906020012090506108a781866111e2565b85877fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8287604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a38093505050509392505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610a145750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610a1d57600080fd5b837f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6884604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050505050565b6000610ab6826110b2565b610b6f57600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166316a25cbd836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610b2d57600080fd5b505afa158015610b41573d6000803e3d6000fd5b505050506040513d6020811015610b5757600080fd5b81019080805190602001909291905050509050610b7b565b610b788261122f565b90505b919050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610c7b5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610c8457600080fd5b837f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a084604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a28260008086815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610e3d5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b610e4657600080fd5b610e5084846111e2565b837fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b6000610ec7868686610764565b9050610ed4818484611262565b505050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61100d8484610d42565b611018848383611262565b50505050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff1660008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600080600083815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60008060008084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111d85760009150506111dd565b809150505b919050565b6000819050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611220573090505b61122a8382611455565b505050565b600080600083815260200190815260200160002060010160149054906101000a900467ffffffffffffffff169050919050565b60008084815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611383578160008085815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25b60008084815260200190815260200160002060010160149054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1614611450578060008085815260200190815260200160002060010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa6882604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a25b505050565b8060008084815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505056fea265627a7a72315820e307c1741e952c90d504ae303fa3fa1e5f6265200c65304d90abaa909d2dee4b64736f6c63430005100032","in3":{"proof":{"type":"accountProof","block":"0xf90259a00a54b8e9d1ffc503a90d679e850e689d114ee65dbda6bd256bfa0a0c74a02710a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a06ef90ef4b638b35751749168332059e4464df4110ab5c45c82caecafbe3a9caaa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001832779bd837a120080845ea47dbbb8614e65746865726d696e6420312e372e352d302d6139386364356233302d323032755d5cac15ce476131895d7f6b09624262851b03b73ecee9c2d5e514024459562fac11baa4d62666465f9b58775d9f208026178ccb63f433ee629fee2c6519a800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000","signatures":[{"blockHash":"0xa994ad0969ba090938156ad7fe26769e1f5884c9cb73b3afb22543fec28caf1d","block":2587069,"r":"0x559fc213d5baba30a8a6223a58ffe4748d55db7790e7148760b586ebab8a598e","s":"0x159cfbab8632d45ae0c8aa72788fb5f073b43524850287f22dbca01c611b3ae9","v":27,"msgHash":"0xfbd5922e3b61447281d0b9e5aad1537cd5c8995cc30a865617c3f4686f8c86b9"},{"blockHash":"0xa994ad0969ba090938156ad7fe26769e1f5884c9cb73b3afb22543fec28caf1d","block":2587069,"r":"0x40651d673f8233e5941603390ed4fac759ea0f7a702fdab985296059a22ae9d9","s":"0x47c3deea96007b6369bad6880612932d2800ffa3f46be81f5a52c0a232f332d3","v":28,"msgHash":"0xfbd5922e3b61447281d0b9e5aad1537cd5c8995cc30a865617c3f4686f8c86b9"}],"accounts":{"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e":{"accountProof":["0xf90211a06e3884346d957ebec001e3e8e5004ca1d679d798cc7b10d615d2152e8def48e3a09819676032e879bf9838b85f8f178818bd35e586669672ae937c39cc8aa4493ca0f8f1d8c4d2200a29d919ad79cf76a18a1659b1b9e27cab29262aead09657477aa09693ae7071af1e5a92b5184b8318f4f6b0cb18329007c40e1bec14de2227efc1a0158d3d140de9be8def09f4e69eae0ed3d6c3091c39f8265a10254f8425c164f9a00f067baab004d0994abe913676072f0098c8fe374b644dd02bbf129e9e993724a016bb47179bb030e32abb0cd3367df83ae46f06fbcba9fd04c860bb5f3b12d0f0a0ff8ab35fc5c34ac9fea1ef8657345f78ed296096805427c780012133eefefed9a0d67e2aedef33f705451de8c65410878036aac40429f3ee9fd35f58d959fe19d9a03acac961d509e99bd30b4036c042e1f9f5483de204902809cb428351e6725721a0a7f4dda9e198b90382319b4f0d4b1bfc2f04c8eaa13e2202fdbd48ca56b3000ea0c4ca4b061cb1588d0d6036bfc4a6fbc1de5a9f6d2da5701286da1c35864d49f1a060c5648dccc343d208d0b78f179993b0573caa12d805dd6cbdb3c4e6eee1b44ea0b0c940263c2150bd867850bed2170330c039145bab8d6ba200ca510d792e752ea0463c973251547d2805cfa4802a579579416276e3def59493c76d4f924aa15efca0d09280ad32d2053201bfe890df1d04bb18b39da8d072c11bb7c7a7ef578f919a80","0xf90211a0eccd829d32a260dbd58b39d0ad4fc865fdc2b4fed7e58426318c622ebaa5f02fa07f47fd520453962d0c5673b26c73c21fab0127ddccb0c623a8feabe197ed443da0e4d88df720993b5214761217a6f692636a175cd68afdbdb28810f58b1a6fb0e8a0b50b79fa9186646ca175a7ab32f4103d1273b5fd4e1e455020a5ab9e27541d9fa0ba0fb4c575c2263c7f5bc12d2dc32566f0f45c2907c2452160a6243d98c5e359a0c7c9ee54e08d27465cd96c438ba06c1bdd41f8c4c1c535d3cab1013372995b8ca045184cd142f6b4e085ba7a12f497392988858793e097e62dd8006b62cc2d40e0a0ff22b9b95164fe30e6feb1ff30acf5479949023d94aa84757c5509cc72f14611a04af1b78f7369cb80d294b816ef4150dac587e74b5e4fd1d694ccdc70f7b8dae9a0927c123f2b85b1cc36dadc9a7480bbb0f340f55106a7a191bebb4c02a80eebfda071f77ee6ae59898098022b01af4e9a0629635cd988e513ccd5f0f85ae7af81a8a0d431d1895f12cf91a594383bfb97743e34f0ad2f0f40269e7183ad8a8e3862dba0c2a3691c28c0547264a4d39ee81c4ce8e7826f2013e5b20a2d74d2efd935a44ea08deecacce3e0145aa8590ac58333cd5789024e4bd0cd927853f6198885a82d2ea0022f54fd50be1b7133344374032c146a276d5e68f1c1e9279f04c8c7f9e69120a0d37b2c683614801ddf9a63ef70eab7035afae663229d94e28c428ec6acb9be0880","0xf90211a0ce97293c34549170171bb723390dd47dc53b8237186c1dab1e8c578f181da75ba022c74c0c055f141c9ab5e43754f8dcd806bf80ae7f9280ed841880ba88f41f95a032105d2b5c182771994280ab031f650a6a8cdff20949d04cccad7b46130f913ba0d0f1612ff9f1d9436340ad0d65f68fb5f6df1e2faa764c12af5a9ad96d62761da0b4e8682ab002a59733edf9d308315f88797c6b87c24c9bbba8c56822533d19c9a02f2a237d03b62784f82c9c18405494ed771ea12fcac9b1329e9830ba3ae8d710a029aeee66e4afd9f9bf4433a02ccbb7b2f56d5e8745d0d63c40d5c23dfe75de4ba0d0211b072f1382dac5de0b3d6fcf2b6b52ecdb3cf72d798c09058665c361940fa03f8df8c9f0a9770e8fdeb3d162e2b74d38f2cc8de3e7f776d7a5b24c0408d25da06f1b88bce40ab519418a821f918d9b8006dc165b13e1551209756bd35ea1867fa01796b1002df593ef8c02a9c4b7b07b7003710512f31a964e0c5de0339f95061fa0e70a10f60c513e3ea2ed418df7fd1c70e6a74971edf6cc65cce9dd5217c5766ca067f3b37f5f1ba9862694b0707203e5ae79e3bca5c5b6194ddfbdcae38096d736a0e03870853881d3fec38abc662478cedbe84669b510433b073fa902e99985f586a05a30f44daa3205e3c7ef8a4a42517bc72f7a09757fdd534dac361bef3f7b38ffa09e46a57cab556b233914adb7ed2057cefc8c92e8d9257cf917be5d18ec57052180","0xf90191a090180abf51ee9a8d06b322766f3cf17aade5f5606d54fc17844f062a105e4aab80a09fd4239f754ce994e3f05c29b0800c8fa29ea7476f3d1bb33afcc3b33029b04ea0c32c2ce9a42b69f26eb54ccf4f397f9fa5c64b1289972e00f5df914f3b867d8ea0339ffbbc8b267ba43b478c855cf7c3b65b5681198dbe14a6c383d6e927fb99f1a075f2e6febe371c57c91644ef405b342b831264580cf994fd94c7d42ae554ae9aa0c95784b61cd7b153e42c8e22d91028bcd9b7a440e8bed87d5f54cbfea185b05a80a0918bbbebb389e4c100248c7d1ce4df01aeca2e2214cb89f4c3050d73efdbc28c80a0d8dff14cd8d20fe86f1abcc1d12cc7004b5d82af5fa65b16c6593d6ae3e35d76a04b75c24381c9c971ab560c96baf1e65128510c2a7c71e73b7c4533424eb376d3a02933b22375eaa4148e5cf2f687209eb60f9fc3c93af79e7d09bb7a483e5c922380a07caa3f3785c08bc622dbd2b81f4437c95467a9f137a0e83ece5c5c236cbc03caa0e1f6bc975a6f522766aee88f41212e45ff4519a197cd665fba9421b0242d8bcf80","0xf851808080a0b11c6b2f2d89847435e8696888779533b8556adb7a26799a95a4fe4396868de8808080808080a004765232d3d7c62b886a9855d8074b75a2b597b4dd7ad2e964ed0a0642cb1266808080808080","0xf8679e32ca53e8a0e441d4dc5101efa6a123b85a3a2a219f1a5fd625a5d6614490b846f8440180a0a36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69a0d6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4"],"address":"0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e","balance":"0x0","codeHash":"0xd6bfd5d6f1384a1f6ea57b8a8412de5552f138d42021cf7c4941e33206f529e4","nonce":"0x1","storageHash":"0xa36338b257bf11e77d91eff39ba8d741a65eded04ba0e9de0fc7f2d7cec02c69","storageProof":[]}}},"version":"2.1.0","currentBlock":2587075,"lastValidatorChange":0,"lastNodeList":2586588,"execTime":104,"rpcTime":43,"rpcCount":1}}]',
+ b'https://in3-v2.slock.it/kovan/nd-1': b'',
+ b'https://in3-v2.slock.it/kovan/nd-2': b'',
+ }
+}
diff --git a/python/tests/transport.py b/python/tests/transport.py
new file mode 100644
index 000000000..31248cf90
--- /dev/null
+++ b/python/tests/transport.py
@@ -0,0 +1,44 @@
+"""
+Test transport function for `in3.client.Client`.
+
+Collect mocked responses from `http_ok.py`.
+"""
+import ctypes as c
+import json
+
+from in3.libin3.lib_loader import libin3
+from in3.transport import In3Request
+
+
+@c.CFUNCTYPE(c.c_int, c.POINTER(In3Request))
+def mock_transport(in3_request: In3Request, positive: bool = True):
+ """
+ Transports each request coming from libin3 to the in3 network and and reports the answer back
+ Args:
+ in3_request (In3Request): request sent by the In3 Client Core to the In3 Network
+ positive: True for positive tests, False for negative (must fail nicely) tests
+ Returns:
+ exit_status (int): Always zero for signaling libin3 the function executed OK.
+ """
+ if positive:
+ from tests.mock import http_ok as mock
+ else:
+ from tests.mock import http_fail as mock
+ in3_request = in3_request.contents
+
+ for i in range(0, in3_request.urls_len):
+ try:
+ http_request = {
+ 'url': c.string_at(in3_request.urls[i]),
+ 'data': c.string_at(in3_request.payload),
+ 'headers': {'Content-type': 'application/json'},
+ 'timeout': in3_request.timeout
+ }
+ request_data = json.loads(http_request['data'])[0]
+ request_method = request_data['method']
+ response = mock.data[request_method][http_request['url']]
+ libin3.in3_req_add_response(in3_request.results, i, False, response, len(response))
+ except Exception as err:
+ err_bytes = str(err).encode('utf8')
+ libin3.in3_req_add_response(in3_request.results, i, True, err_bytes, len(str(err)))
+ return 0
diff --git a/rust/ci.yml b/rust/ci.yml
index e01829557..3e13080b8 100644
--- a/rust/ci.yml
+++ b/rust/ci.yml
@@ -1,3 +1,11 @@
+.only_rust:
+ rules:
+ - changes:
+ - rust/**/*
+ - 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"'
+
rust:
image: docker.slock.it/build-images/cmake:rust
stage: bindings
@@ -27,6 +35,7 @@ rust:
test_rust:
image: docker.slock.it/build-images/cmake:rust
stage: rust
+ extends: .only_rust
needs:
- rust
tags:
@@ -40,6 +49,7 @@ test_rust:
examples_rust:
image: docker.slock.it/build-images/cmake:rust
stage: rust
+ extends: .only_rust
needs:
- rust
tags:
diff --git a/rust/in3-rs/Cargo.toml b/rust/in3-rs/Cargo.toml
index 1d32c8602..e5a0f7f41 100644
--- a/rust/in3-rs/Cargo.toml
+++ b/rust/in3-rs/Cargo.toml
@@ -6,16 +6,18 @@ description = "High level bindings to IN3 library"
edition = "2018"
[features]
-blocking = ["reqwest"]
+blocking = ["async-std"]
[dependencies]
in3-sys = { path = "../in3-sys" }
libc = { version = "0.2", default-features = false }
-reqwest = { version = "0.10", features = ["blocking","json"], optional = true }
serde_json = "1.0"
-openssl = {version = "0.10", features = ["vendored"]}
surf = "1.0.3"
-serde = "1.0.106"
+serde = { version = "1.0.106", features = ["derive"] }
+ethereum-types = "0.9.0"
+rustc-hex = "1.0.0"
+async-trait = "0.1.30"
+async-std = {version = "1.5.0", optional = true}
[dev-dependencies]
-async-std = "1.5.0"
\ No newline at end of file
+async-std = "1.5.0"
diff --git a/rust/in3-rs/examples/custom_storage.rs b/rust/in3-rs/examples/custom_storage.rs
index 4084cd78e..08d1393d6 100644
--- a/rust/in3-rs/examples/custom_storage.rs
+++ b/rust/in3-rs/examples/custom_storage.rs
@@ -2,32 +2,46 @@ extern crate in3;
use std::fs;
+use async_std::task;
+
use in3::prelude::*;
-const CACHE_PATH: &str = "cache";
+struct FsStorage<'a> {
+ dir: &'a str,
+}
+
+impl FsStorage<'_> {
+ fn new(dir: &str) -> FsStorage {
+ fs::create_dir_all(dir).unwrap();
+ FsStorage { dir }
+ }
+}
+
+impl Storage for FsStorage<'_> {
+ fn get(&self, key: &str) -> Option> {
+ println!("FsStorage log: get {}", key);
+ match fs::read(format!("{}/{}", self.dir, key)) {
+ Ok(value) => Some(value),
+ Err(_) => None,
+ }
+ }
+
+ fn set(&mut self, key: &str, value: &[u8]) {
+ println!("FsStorage log: set {}", key);
+ fs::write(format!("{}/{}", self.dir, key), value).expect("Unable to write file");
+ }
+
+ fn clear(&mut self) {
+ println!("FsStorage log: clear");
+ fs::remove_dir_all(format!("{}", self.dir)).unwrap();
+ }
+}
fn main() {
let mut c = Client::new(chain::MAINNET);
- fs::create_dir_all(CACHE_PATH).unwrap();
- c.set_storage(
- Box::new(|key| -> Vec {
- println!("get {}", key);
- match fs::read(format!("{}/{}", CACHE_PATH, key)) {
- Ok(value) => value,
- Err(_) => vec![],
- }
- }),
- Box::new(|key, value| {
- println!("set {} -> {:?}", key, value);
- fs::write(format!("{}/{}", CACHE_PATH, key), value).expect("Unable to write file");
- }),
- Box::new(|| {
- println!("clear");
- fs::remove_dir_all(format!("{}", CACHE_PATH)).unwrap();
- }),
- );
- match c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#) {
+ c.set_storage(Box::new(FsStorage::new("cache")));
+ match task::block_on(c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#)) {
Ok(res) => println!("{}", res),
- Err(err) => println!("{}", err),
+ Err(err) => println!("Failed with error: {}", err),
}
}
diff --git a/rust/in3-rs/examples/custom_transport.rs b/rust/in3-rs/examples/custom_transport.rs
index 8332876a1..c5b0b63f5 100644
--- a/rust/in3-rs/examples/custom_transport.rs
+++ b/rust/in3-rs/examples/custom_transport.rs
@@ -1,17 +1,23 @@
extern crate in3;
+use async_std::task;
+
+use async_trait::async_trait;
use in3::prelude::*;
+use in3::transport::MockTransport;
+
fn main() {
let mut c = Client::new(chain::MAINNET);
let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- c.set_transport(Box::new(|_payload: &str, _urls: &[&str]| {
- let mut responses = vec![];
- responses.push(Ok(r#"{"jsonrpc":"2.0","id":1,"result":"0x948f0d","in3":{"lastValidatorChange":0,"lastNodeList":9698978,"execTime":454,"rpcTime":454,"rpcCount":1,"currentBlock":9735949,"version":"2.1.0"}}"#.to_string()));
- responses
+ c.set_transport(Box::new(MockTransport {
+ responses: vec![(
+ "eth_blockNumber",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x96bacd"}]"#,
+ )],
}));
- match c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#) {
+ match task::block_on(c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#)) {
Ok(res) => println!("{}", res),
- Err(err) => println!("{}", err),
+ Err(err) => println!("Failed with error: {}", err),
}
}
diff --git a/rust/in3-rs/examples/eth_api.rs b/rust/in3-rs/examples/eth_api.rs
new file mode 100644
index 000000000..4ab10ff21
--- /dev/null
+++ b/rust/in3-rs/examples/eth_api.rs
@@ -0,0 +1,87 @@
+use std::convert::TryInto;
+
+use async_std::task;
+use ethereum_types::{Address, U256};
+
+use in3::eth1::*;
+use in3::prelude::*;
+use in3::types::Bytes;
+
+fn main() -> In3Result<()> {
+ // configure client and API
+ let mut eth_api = Api::new(Client::new(chain::MAINNET));
+ eth_api
+ .client()
+ .configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#)?;
+
+ // eth_getStorageAt
+ let address: Address = serde_json::from_str(r#""0x0123456789012345678901234567890123456789""#)?;
+ let key: U256 = 0u64.into();
+ let storage: u64 = task::block_on( eth_api.get_storage_at(address, key, BlockNumber::Latest))?
+ .try_into()
+ .unwrap();
+ println!("Storage value is {:?}", storage);
+
+ // eth_getCode
+ let address: Address = serde_json::from_str(r#""0xac1b824795e1eb1f6e609fe0da9b9af8beaab60f""#)?;
+ let code: Bytes = task::block_on(eth_api.get_code(address, BlockNumber::Latest))?
+ .try_into()
+ .unwrap();
+ println!("Code at address {:?} is {:?}", address, code);
+
+ // eth_blockNumber
+ let latest_blk_num: u64 = task::block_on(eth_api.block_number())?.try_into().unwrap();
+ println!("Latest block number is {:?}", latest_blk_num);
+
+ // eth_gasPrice
+ let gas_price: u64 = task::block_on(eth_api.gas_price())?.try_into().unwrap();
+ println!("Gas price is {:?}", gas_price);
+
+ // eth_getBalance
+ let address: Address = serde_json::from_str(r#""0x0123456789012345678901234567890123456789""#)?;
+ let balance: u64 = task::block_on(
+ eth_api.get_balance(address, BlockNumber::Number((latest_blk_num - 10).into())),
+ )?
+ .try_into()
+ .unwrap();
+ println!("Balance of address {:?} is {:?} wei", address, balance);
+
+ // eth_getBlockByNumber
+ let block: Block = task::block_on(eth_api.get_block_by_number(BlockNumber::Latest, false))?;
+ println!("Block => {:?}", block);
+
+ // eth_getBlockByHash
+ let hash: Hash = serde_json::from_str(
+ r#""0xa2ad3d67e3a09d016ab72e40fc1e47d6662f9156f16ce1cce62d5805a62ffd02""#,
+ )?;
+ let block: Block = task::block_on(eth_api.get_block_by_hash(hash, false))?;
+ println!("Block => {:?}", block);
+
+ // eth_getLogs
+ let logs: Vec = task::block_on(eth_api.get_logs(serde_json::json!({
+ "blockHash": "0x468f88ed8b40d940528552f093a11e4eb05991c787608139c931b0e9782ec5af",
+ "topics": ["0xa61b5dec2abee862ab0841952bfbc161b99ad8c14738afa8ed8d5c522cd03946"]
+ })))?;
+ println!("Logs => {:?}", logs);
+
+ // eth_call
+ let contract: Address =
+ serde_json::from_str(r#""0x2736D225f85740f42D17987100dc8d58e9e16252""#).unwrap();
+ let mut abi = abi::In3EthAbi::new();
+ let params =
+ task::block_on(abi.encode("totalServers():uint256", serde_json::json!([]))).unwrap();
+ let txn = CallTransaction {
+ to: Some(contract),
+ data: Some(params),
+ ..Default::default()
+ };
+ let output: Bytes = task::block_on(eth_api.call(txn, BlockNumber::Latest))
+ .unwrap()
+ .try_into()
+ .unwrap();
+ let output = task::block_on(abi.decode("uint256", output)).unwrap();
+ let total_servers: U256 = serde_json::from_value(output).unwrap();
+ println!("{:?}", total_servers);
+
+ Ok(())
+}
diff --git a/rust/in3-rs/examples/eth_block_number.rs b/rust/in3-rs/examples/eth_block_number.rs
deleted file mode 100644
index 065dc0115..000000000
--- a/rust/in3-rs/examples/eth_block_number.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Make sure you build the in3 crate with blocking feature enabled to make this example work
-// cargo run --example eth_block_number --features=blocking
-extern crate in3;
-
-use in3::prelude::*;
-
-fn main() {
- let mut c = Client::new(chain::MAINNET);
- let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- match c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#) {
- Ok(res) => println!("{}", res),
- Err(err) => println!("{}", err),
- }
-}
diff --git a/rust/in3-rs/examples/send.rs b/rust/in3-rs/examples/send.rs
deleted file mode 100644
index 0441d4e18..000000000
--- a/rust/in3-rs/examples/send.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-extern crate in3;
-
-use async_std::task;
-
-use in3::prelude::*;
-
-fn send() {
- let mut c = Client::new(chain::MAINNET);
- let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- let mut ctx = Ctx::new(&mut c, r#"{"method": "eth_blockNumber", "params": []}"#);
- c.send(&mut ctx);
-}
-
-async fn send_request() {
- let mut c = Client::new(chain::MAINNET);
- let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- c.send_request(r#"{"method": "eth_blockNumber", "params": []}"#)
- .await;
-}
-
-fn send_execute() {
- let mut c = Client::new(chain::MAINNET);
- let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- let mut ctx = Ctx::new(&mut c, r#"{"method": "eth_blockNumber", "params": []}"#);
- let _res = ctx.execute();
-}
-
-fn rpc_call() {
- let mut c = Client::new(chain::MAINNET);
- let _ = c.configure(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- match c.rpc(r#"{"method": "eth_blockNumber", "params": []}"#) {
- Ok(res) => println!("{}", res),
- Err(err) => println!("{}", err),
- }
-}
-
-fn main() {
- //rpc_call();
- let future = send_request();
- task::block_on(future);
- // add tasks and run on executor.
- //send_request();
-}
diff --git a/rust/in3-rs/examples/sign.rs b/rust/in3-rs/examples/sign.rs
new file mode 100644
index 000000000..dc58a7757
--- /dev/null
+++ b/rust/in3-rs/examples/sign.rs
@@ -0,0 +1,157 @@
+// extern crate abi;
+// extern crate in3;
+use async_std::task;
+use async_trait::async_trait;
+use ethereum_types::{Address, U256};
+use ffi::{CStr, CString};
+use in3::eth1::api::RpcRequest;
+use in3::eth1::*;
+use in3::prelude::*;
+use in3::signer;
+use in3::signer::SignatureType;
+use libc::c_char;
+use rustc_hex::{FromHex, ToHex};
+use serde_json::json;
+use std::collections::HashMap;
+use std::ffi;
+use std::fmt::Write;
+use std::num::ParseIntError;
+use std::str;
+// use crate::transport::MockTransport;
+
+unsafe fn signature_hex_string(data: *mut u8) -> String {
+ let value = std::slice::from_raw_parts_mut(data, 65 as usize);
+ let mut sign_str = "".to_string();
+ for byte in value {
+ let mut tmp = "".to_string();
+ write!(&mut tmp, "{:02x}", byte).unwrap();
+ sign_str.push_str(tmp.as_str());
+ }
+ println!(" signature {}", sign_str);
+ sign_str
+}
+
+fn sign() {
+ unsafe {
+ //Private key
+ let pk = "889dbed9450f7a4b68e0732ccb7cd016dab158e6946d16158f2736fda1143ca6";
+ //Message to sign
+ let msg = "9fa034abf05bd334e60d92da257eb3d66dd3767bba9a1d7a7575533eb0977465";
+ // decode Hex msg
+ let msg_hex = msg.from_hex().unwrap();
+ let raw_msg_ptr = msg_hex.as_ptr() as *const c_char;
+ // pk to raw ptr
+ let pk_hex = pk.from_hex().unwrap();
+ let raw_pk = pk_hex.as_ptr() as *mut u8;
+ //Sign the message raw
+ let signature_raw = signer::sign(raw_pk, SignatureType::Raw, raw_msg_ptr, msg_hex.len());
+ let sig_raw_expected = "f596af3336ac65b01ff4b9c632bc8af8043f8c11ae4de626c74d834412cb5a234783c14807e20a9e665b3118dec54838bd78488307d9175dd1ff13eeb67e05941c";
+ assert_eq!(signature_hex_string(signature_raw), sig_raw_expected);
+ // Hash and sign the msg
+ let signature_hash = signer::sign(raw_pk, SignatureType::Hash, raw_msg_ptr, msg_hex.len());
+ let sig_hash_expected = "349338b22f8c19d4c8d257595493450a88bb51cc0df48bb9b0077d1d86df3643513e0ab305ffc3d4f9a0f300d501d16556f9fb43efd1a224d6316012bb5effc71c";
+ assert_eq!(signature_hex_string(signature_hash), sig_hash_expected);
+ }
+}
+
+fn sign_tx_api() {
+ //Config in3 api client
+ let mut eth_api = Api::new(Client::new(chain::MAINNET));
+ let responses = vec![
+ (
+ "eth_estimateGas",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x96c0"}]"#,
+ ),
+ (
+ "eth_sendRawTransaction",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0xd5651b7c0b396c16ad9dc44ef0770aa215ca795702158395713facfbc9b55f38"}]"#,
+ ),
+ (
+ "eth_gasPrice",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x9184e72a000"}]"#,
+ ),
+ (
+ "eth_getTransactionCount",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x0"}]"#,
+ ),
+ ];
+ eth_api.client().configure(
+ r#"{"proof":"none", "autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#,
+ );
+ eth_api
+ .client()
+ .set_pk_signer("0x889dbed9450f7a4b68e0732ccb7cd016dab158e6946d16158f2736fda1143ca6");
+ eth_api.client().set_transport(Box::new(MockTransport {
+ responses: responses,
+ }));
+ let mut abi = abi::In3EthAbi::new();
+ let params = task::block_on(abi.encode(
+ "setData(uint256,string)",
+ serde_json::json!([123, "testdata"]),
+ ))
+ .unwrap();
+ println!("{:?}", params);
+ let to: Address =
+ serde_json::from_str(r#""0x1234567890123456789012345678901234567890""#).unwrap();
+ let from: Address =
+ serde_json::from_str(r#""0x3fEfF9E04aCD51062467C494b057923F771C9423""#).unwrap();
+ let txn = OutgoingTransaction {
+ to: to,
+ from: from,
+ data: Some(params),
+ ..Default::default()
+ };
+
+ let hash: Hash = task::block_on(eth_api.send_transaction(txn)).unwrap();
+ println!("Hash => {:?}", hash);
+}
+
+fn sign_tx_rpc() {
+ //Config in3 api client
+ let mut c = Client::new(chain::MAINNET);
+ let _ = c.configure(
+ r#"{"proof":"none","autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#,
+ );
+ let responses = vec![
+ (
+ "eth_estimateGas",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x1e8480"}]"#,
+ ),
+ (
+ "eth_getTransactionCount",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0x0"}]"#,
+ ),
+ (
+ "eth_sendRawTransaction",
+ r#"[{"jsonrpc":"2.0","id":1,"result":"0xd5651b7c0b396c16ad9dc44ef0770aa215ca795702158395713facfbc9b55f38"}]"#,
+ ),
+ ];
+ c.set_transport(Box::new(MockTransport {
+ responses: responses,
+ }));
+ c.set_pk_signer("0x8da4ef21b864d2cc526dbdb2a120bd2874c36c9d0a1fb7f8c63d7f7a8b41de8f");
+ let tx = json!([{
+ "from": "0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377",
+ "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
+ "gas": "0x96c0",
+ "gasPrice": "0x9184e72a000",
+ "value": "0x9184e72a",
+ "nonce": "0x0",
+ "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
+ }]);
+ let rpc_req = RpcRequest {
+ method: "eth_sendTransaction",
+ params: tx,
+ };
+ let req_str = serde_json::to_string(&rpc_req).unwrap();
+ match task::block_on(c.rpc(&req_str)) {
+ Ok(res) => println!("RESPONSE > {:?}, {:?}\n\n", req_str, res),
+ Err(err) => println!("Failed with error: {}\n\n", err),
+ }
+}
+
+fn main() {
+ sign_tx_api();
+ sign_tx_rpc();
+ sign();
+}
diff --git a/rust/in3-rs/src/api.rs b/rust/in3-rs/src/api.rs
deleted file mode 100644
index 56e46aaa4..000000000
--- a/rust/in3-rs/src/api.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use std::i64;
-
-use serde_json::{Result, Value};
-use serde_json::json;
-
-use crate::error::*;
-use crate::error::In3Result;
-use crate::in3::*;
-
-pub struct EthApi {
- client: Box,
-}
-
-impl EthApi {
- pub fn new(config_str: &str) -> EthApi {
- let mut client = Client::new(chain::MAINNET);
- let _ = client.configure(config_str);
- EthApi { client }
- }
-
- async fn send(mut self, params: &str) -> In3Result {
- self.client.send_request(params).await
- }
-
- pub async fn block_number(self) -> i64 {
- let response =
- self.send(r#"{"method": "eth_blockNumber", "params": []}"#).await;
- let v: Value = serde_json::from_str(&response.unwrap()).unwrap();
- let ret = v[0]["result"].as_str().unwrap();
- let without_prefix = ret.trim_start_matches("0x");
- let blocknum = i64::from_str_radix(without_prefix, 16);
- blocknum.unwrap_or(-1)
- }
-
- pub async fn getBalance(self, address: String) -> String {
- let payload = json!({
- "method": "eth_getBalance",
- "params": [
- address,
- "latest"
- ]
- });
- let serialized = serde_json::to_string(&payload).unwrap();
- let response = self.send(&serialized).await;
- let v: Value = serde_json::from_str(&response.unwrap()).unwrap();
- let balance = v[0]["result"].as_str().unwrap();
- balance.to_string()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use async_std::task;
-
- use super::*;
-
- #[test]
- fn test_block_number() {
- let api = EthApi::new(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- //execute the call to the api on task::block_on
- let num = task::block_on(api.block_number());
- assert!(num > 9000000, "Block number is not correct");
- }
-
- #[test]
- fn test_get_balance() {
- let api = EthApi::new(r#"{"autoUpdateList":false,"nodes":{"0x1":{"needsUpdate":false}}}}"#);
- //execute the call to the api on task::block_on
- let num = task::block_on(
- api.getBalance("0xc94770007dda54cF92009BFF0dE90c06F603a09f".to_string()),
- );
- assert!(num != "", "Balance is not correct");
- }
-}
diff --git a/rust/in3-rs/src/error.rs b/rust/in3-rs/src/error.rs
index a897ae458..eee6a7d81 100644
--- a/rust/in3-rs/src/error.rs
+++ b/rust/in3-rs/src/error.rs
@@ -1,12 +1,12 @@
use core::fmt;
use core::result;
-use std::ffi;
+use std::{convert, ffi};
use in3_sys::in3_ret_t::*;
macro_rules! in3_error_def {
( $( $( #[$attr:meta] )* => $rust_variant:ident = $cs_variant:ident; )* ) => {
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
+ #[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Error {
$(
@@ -17,7 +17,8 @@ macro_rules! in3_error_def {
)*
UnknownIn3Error,
- CustomError(&'static str),
+ TryAgain,
+ CustomError(String),
}
impl From for Error {
@@ -76,8 +77,8 @@ impl fmt::Display for Error {
impl Error {
fn description(&self) -> &str {
use self::Error::*;
- match *self {
- CustomError(msg) => msg,
+ match self {
+ CustomError(ref msg) => msg,
UnknownIn3Error => "Unknown error",
_ => unsafe {
ffi::CStr::from_ptr(in3_sys::in3_errmsg(self.into()))
@@ -88,6 +89,24 @@ impl Error {
}
}
+impl convert::From